package xcmg.device.service.delivery;

import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;
import xcmg.device.dao.entity.DataDictionaryDO;
import xcmg.device.dao.entity.PriMaterialsDO;
import xcmg.device.dao.entity.PubMaterialsDO;
import xcmg.device.dao.entity.abnormal.AbnormalOutDO;
import xcmg.device.dao.entity.barcode.BarcodeManageDO;
import xcmg.device.dao.entity.basic.SystemParameter;
import xcmg.device.dao.entity.boxup.BoxupDetailDO;
import xcmg.device.dao.entity.boxup.BoxupDetailTotalDO;
import xcmg.device.dao.entity.boxup.BoxupMainDO;
import xcmg.device.dao.entity.boxup.DeliveryReceiptDetailDO;
import xcmg.device.dao.entity.company.CompanyInfoDO;
import xcmg.device.dao.entity.delivery.DeliveryNoteDO;
import xcmg.device.dao.entity.delivery.DeliveryNoteDetailDO;
import xcmg.device.dao.entity.delivery.DeliveryReceiptDO;
import xcmg.device.dao.entity.delivery.DeliveryReceiptExportDO;
import xcmg.device.dao.entity.delivery.DeliveryReceiptLinkDO;
import xcmg.device.dao.entity.delivery.DeliveryReceiptLogisticsDO;
import xcmg.device.dao.entity.delivery.DeliveryReceiptMaterialDO;
import xcmg.device.dao.entity.delivery.LogisticsBasicWeightDO;
import xcmg.device.dao.entity.delivery.ReceiptInDO;
import xcmg.device.dao.entity.delivery.ReceiptInDetailDO;
import xcmg.device.dao.entity.packageSpec.PackageSpecDO;
import xcmg.device.dao.entity.purchase.PurchaseRequestDO;
import xcmg.device.dao.entity.purchase.PurchaseRequestDetailDO;
import xcmg.device.dao.entity.sale.SaleIntentionDO;
import xcmg.device.dao.entity.sale.SalesBillDO;
import xcmg.device.dao.entity.sale.SalesOutBillDO;
import xcmg.device.dao.entity.threeGuaranteesPur.ThreeGuaranteesOutDO;
import xcmg.device.dao.entity.threeGuaranteesPur.ThreeGuaranteesOutDetailDO;
import xcmg.device.dao.entity.threeGuaranteesPur.ThreeGuaranteesPurDO;
import xcmg.device.dao.entity.threedayplan.ThreeDayPlanDetailDO;
import xcmg.device.dao.entity.warehouse.AbnormalInDO;
import xcmg.device.dao.entity.warehouse.AbnormalInDetailDO;
import xcmg.device.dao.entity.warehouse.WarehouseDO;
import xcmg.device.dao.entity.warehouse.WarehouseDeliveryDetailDO;
import xcmg.device.dao.entity.warehouse.WarehouseDeliveryRecordDO;
import xcmg.device.dao.entity.warehouse.WarehouseInboundDO;
import xcmg.device.dao.entity.warehouse.WarehouseInboundDetailDO;
import xcmg.device.dao.entity.warehouse.WarehouseInboundRecordDO;
import xcmg.device.dao.entity.warehouse.allot.RegionAllotDO;
import xcmg.device.dao.mapper.BarcodeManageMapper;
import xcmg.device.dao.mapper.BoxupDetailMapper;
import xcmg.device.dao.mapper.BoxupMainMapper;
import xcmg.device.dao.mapper.CompanyInfoMapper;
import xcmg.device.dao.mapper.DataDictionaryMapper;
import xcmg.device.dao.mapper.DeliveryReceiptDetailMapper;
import xcmg.device.dao.mapper.PriMaterialsMapper;
import xcmg.device.dao.mapper.PubMaterialsMapper;
import xcmg.device.dao.mapper.PurchaseRequestDetailMapper;
import xcmg.device.dao.mapper.PurchaseRequestMapper;
import xcmg.device.dao.mapper.SaleIntentionMapper;
import xcmg.device.dao.mapper.abnormal.AbnormalOutDetailMapper;
import xcmg.device.dao.mapper.abnormal.AbnormalOutMapper;
import xcmg.device.dao.mapper.delivery.DeliveryNoteDetailMapper;
import xcmg.device.dao.mapper.delivery.DeliveryNoteMapper;
import xcmg.device.dao.mapper.delivery.DeliveryReceiptLinkMapper;
import xcmg.device.dao.mapper.delivery.DeliveryReceiptLogisticsMapper;
import xcmg.device.dao.mapper.delivery.DeliveryReceiptMapper;
import xcmg.device.dao.mapper.delivery.DeliveryReceiptMaterialMapper;
import xcmg.device.dao.mapper.delivery.ExpressCodeInfoMapper;
import xcmg.device.dao.mapper.delivery.ReceiptInDetailMapper;
import xcmg.device.dao.mapper.delivery.ReceiptInMapper;
import xcmg.device.dao.mapper.packageSpec.PackageSpecDOMapper;
import xcmg.device.dao.mapper.sale.SalesBillMapper;
import xcmg.device.dao.mapper.sale.SalesOutBillDetailMapper;
import xcmg.device.dao.mapper.sale.SalesOutBillMapper;
import xcmg.device.dao.mapper.threeGuaranteesPur.ThreeGuaranteesOutDetailMapper;
import xcmg.device.dao.mapper.threeGuaranteesPur.ThreeGuaranteesOutMapper;
import xcmg.device.dao.mapper.threeGuaranteesPur.ThreeGuaranteesPurDetailMapper;
import xcmg.device.dao.mapper.threeGuaranteesPur.ThreeGuaranteesPurMapper;
import xcmg.device.dao.mapper.threedayplan.ThreeDayPlanDOMapper;
import xcmg.device.dao.mapper.threedayplan.ThreeDayPlanDetailDOMapper;
import xcmg.device.dao.mapper.warehouse.AbnormalInDetailMapper;
import xcmg.device.dao.mapper.warehouse.AbnormalInMapper;
import xcmg.device.dao.mapper.warehouse.RegionAllotDetailMapper;
import xcmg.device.dao.mapper.warehouse.RegionAllotMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseAreaLocationDOMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseDOMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseDeliveryDetailMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseDeliveryMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseDeliveryRecordMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseInboundDetailMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseInboundMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseInboundRecordMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseInventoryMapper;
import xcmg.device.infra.BeanUtil;
import xcmg.device.infra.DateUtil;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.ExportUtil;
import xcmg.device.infra.FileUtil;
import xcmg.device.infra.StringUtil;
import xcmg.device.infra.enums.BillDesc;
import xcmg.device.infra.enums.DeliveryReceiptAuditStatusEnum;
import xcmg.device.infra.enums.DeliveryReceiptEnum;
import xcmg.device.infra.enums.SaleStatus;
import xcmg.device.service.GenDocumentService;
import xcmg.device.service.basic.SystemParameterService;
import xcmg.device.service.boxup.BoxupMainService;
import xcmg.device.service.company.CompanyInfoService;
import xcmg.device.service.crm.util.ActionResultUtil;
import xcmg.device.service.packageSpec.PackageSpecService;
import xcmg.device.service.sale.SaleIntentionService;
import xcmg.device.service.vo.abnormal.AbnormalOutVO;
import xcmg.device.service.vo.boxup.BoxupDetailVO;
import xcmg.device.service.vo.boxup.BoxupMainVO;
import xcmg.device.service.vo.boxup.BoxupMaterialsQuery;
import xcmg.device.service.vo.company.CompanyInfoVO;
import xcmg.device.service.vo.delivery.AutoDeliveryReceiptVO;
import xcmg.device.service.vo.delivery.BillDetailArrivalTimeAndBackFactoryDeitVO;
import xcmg.device.service.vo.delivery.BillDetailArrivalTimeEditVO;
import xcmg.device.service.vo.delivery.BillDetailMaterialsVO;
import xcmg.device.service.vo.delivery.BoxInfoVO;
import xcmg.device.service.vo.delivery.DeliveryNoteAddVO;
import xcmg.device.service.vo.delivery.DeliveryNoteDetailVO;
import xcmg.device.service.vo.delivery.DeliveryNoteVO;
import xcmg.device.service.vo.delivery.DeliveryReceipt4AutoVO;
import xcmg.device.service.vo.delivery.DeliveryReceiptDetailVO;
import xcmg.device.service.vo.delivery.DeliveryReceiptLinkVO;
import xcmg.device.service.vo.delivery.DeliveryReceiptLogisticsVO;
import xcmg.device.service.vo.delivery.DeliveryReceiptMaterialVO;
import xcmg.device.service.vo.delivery.DeliveryReceiptQueryParam;
import xcmg.device.service.vo.delivery.DeliveryReceiptVO;
import xcmg.device.service.vo.delivery.DeliveryStatusVO;
import xcmg.device.service.vo.delivery.LogisticsBasicDataVO;
import xcmg.device.service.vo.delivery.OperateDeliveryReceiptVO;
import xcmg.device.service.vo.delivery.OutBillItemVO;
import xcmg.device.service.vo.delivery.OutBillParamVO;
import xcmg.device.service.vo.delivery.OutBillValuesVO;
import xcmg.device.service.vo.delivery.PrintDeliveryReceiptDetailVO;
import xcmg.device.service.vo.delivery.PrintDeliveryReceiptVO;
import xcmg.device.service.vo.delivery.PrintInfoVO;
import xcmg.device.service.vo.delivery.ReceiptInAddVO;
import xcmg.device.service.vo.delivery.ReceiptInDetailVO;
import xcmg.device.service.vo.delivery.ReceiptInVO;
import xcmg.device.service.vo.delivery.billMaterialsParamVO;
import xcmg.device.service.vo.permission.WareHousePermission;
import xcmg.device.service.vo.sale.SaleAddVO;
import xcmg.device.service.vo.sale.SaleIntentionDetailVO;
import xcmg.device.service.vo.sale.SaleIntentionVO;
import xcmg.device.service.vo.sale.SalesOutBillVO;
import xcmg.device.service.vo.threeGuaranteesPur.ThreeGuaServiceVO;
import xcmg.device.service.vo.threeGuaranteesPur.ThreeGuaranteesOutVO;
import xcmg.device.service.vo.threedayplan.DlvInfoQueryVO;
import xcmg.device.service.vo.warehouse.BillTypeConfigVO;
import xcmg.device.service.vo.warehouse.DeliveryReceiptInDetailVO;
import xcmg.device.service.vo.warehouse.DeliveryReceiptInVO;
import xcmg.device.service.vo.warehouse.WarehouseDeliveryDetailVO;
import xcmg.device.service.vo.warehouse.WarehouseDeliveryRecordAddVO;
import xcmg.device.service.vo.warehouse.WarehouseDeliveryRecordBatchAddVO;
import xcmg.device.service.vo.warehouse.WarehouseDeliveryRecordVO;
import xcmg.device.service.vo.warehouse.WarehouseInboundRecordAddVO;
import xcmg.device.service.vo.warehouse.WarehouseInboundRecordVO;
import xcmg.device.service.vo.warehouse.allot.RegionAllotVO;
import xcmg.device.service.warehouse.BillTypeConfigService;
import xcmg.device.service.warehouse.CommonService;
import xcmg.device.service.warehouse.DepartmentWarehouseRelationService;
import xcmg.device.service.warehouse.WarehouseDeliveryRecordService;
import xcmg.device.service.warehouse.WarehouseInboundRecordService;
import xcmg.device.service.warehouse.WarehouseInventoryService;
import xcmg.device.service.warehouse.allot.RegionAllotService;
import xcmg.device.util.CompanyUtil;
import xcmg.device.util.DecimalUtil;
import yb.ecp.fast.dto.UserCacheDTO;
import yb.ecp.fast.dto.UserDetailDTO;
import yb.ecp.fast.feign.AuthClient;
import yb.ecp.fast.feign.FastGenClient;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.infra.log.LogHelper;
import yb.ecp.fast.infra.util.ListUtil;
import yb.ecp.fast.infra.util.PageHelperPlus;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * Created by sqq on 2018/1/13.
 */

@Service
@Slf4j
public class DeliveryReceiptService {

    @Autowired
    private DeliveryReceiptMapper deliveryReceiptMapper;

    @Autowired
    private DeliveryReceiptLinkMapper deliveryReceiptLinkMapper;

    @Autowired
    private CompanyInfoService companyInfoService;

    @Autowired
    private FastGenClient fastGenClient;

    @Autowired
    private DataDictionaryMapper dataDictionaryMapper;

    @Autowired
    private GenDocumentService genDocumentService;

    @Autowired
    private BoxupMainMapper boxupMainMapper;

    @Autowired
    private BoxupDetailMapper boxupDetailMapper;

    @Autowired
    private DeliveryNoteDetailMapper deliveryNoteDetailMapper;

    @Autowired
    private DeliveryReceiptDetailMapper deliveryReceiptDetailMapper;

    @Autowired
    private BoxupMainService boxupMainService;

    @Autowired
    private DeliveryReceiptLogisticsMapper deliveryReceiptLogisticsMapper;

    @Autowired
    private AuthClient authClient;

    @Autowired
    private HttpServletResponse response;

    @Autowired
    private DeliveryNoteMapper deliveryNoteMapper;

    @Autowired
    private ThreeGuaranteesOutMapper threeGuaranteesOutMapper;

    @Autowired
    private ThreeGuaranteesPurMapper threeGuaranteesPurMapper;

    @Autowired
    private RegionAllotMapper regionAllotMapper;

    @Autowired
    private CompanyInfoMapper companyInfoMapper;

    @Autowired
    private ThreeGuaranteesOutDetailMapper threeGuaranteesOutDetailMapper;

    @Autowired
    private RegionAllotDetailMapper regionAllotDetailMapper;

    @Autowired
    private AbnormalOutMapper abnormalOutMapper;

    @Autowired
    private AbnormalOutDetailMapper abnormalOutDetailMapper;

    @Autowired
    private WarehouseDeliveryDetailMapper warehouseDeliveryDetailMapper;

    @Autowired
    private PriMaterialsMapper priMaterialsMapper;

    @Autowired
    private CommonService commonService;

    @Autowired
    private BillTypeConfigService billTypeConfigService;

    @Autowired
    private LogisticsBasicDataService logisticsBasicDataService;


    @Autowired
    private AbnormalInMapper abnormalInMapper;

    @Autowired
    private WarehouseAreaLocationDOMapper warehouseAreaLocationDOMapper;

    @Autowired
    private AbnormalInDetailMapper abnormalInDetailMapper;

    @Autowired
    private WarehouseInboundDetailMapper warehouseInboundDetailMapper;
    @Autowired
    private WarehouseInboundMapper warehouseInboundMapper;

    @Autowired
    private DeliveryReceiptMaterialService deliveryReceiptMaterialService;
    @Autowired
    private DeliveryReceiptMaterialMapper deliveryReceiptMaterialMapper;

    @Autowired
    private PurchaseRequestMapper purchaseRequestMapper;

    @Autowired
    private SaleIntentionMapper saleIntentionMapper;

    @Autowired
    private PurchaseRequestDetailMapper purchaseRequestDetailMapper;

    @Value("${spring.file.download.path}")
    private String filePath;

    @Autowired
    private SystemParameterService systemParameterService;

    @Autowired
    private ThreeDayPlanDetailDOMapper threeDayPlanDetailDOMapper;
    @Autowired
    private ThreeDayPlanDOMapper threeDayPlanDOMapper;

    @Autowired
    private SalesOutBillMapper salesOutBillMapper;

    @Autowired
    private SalesBillMapper salesBillMapper;

    @Autowired
    private ThreeGuaranteesPurDetailMapper threeGuaranteesPurDetailMapper;

    @Autowired
    private SalesOutBillDetailMapper salesOutBillDetailMapper;
    @Autowired
    private RegionAllotService regionAllotService;
    @Autowired
    private DepartmentWarehouseRelationService relationService;
    @Autowired
    private WarehouseInventoryMapper warehouseInventoryMapper;

    @Autowired
    private CompanyUtil companyUtil;

    /**
     * AUTO_GEN_RECEIPT_SUPPLIER: 创建发货通知单后自动生成发运交接单的主机厂
     * NOT_AUTO_RECEIPT_DEALER: 创建发货通知单后，不自动生成发运交接单的客户
     */
    private static final String AUTO_GEN_RECEIPT_SUPPLIER = "AUTO_GEN_RECEIPT_SUPPLIER", NOT_AUTO_RECEIPT_DEALER = "NOT_AUTO_RECEIPT_DEALER";


    private static final String WJ_ORG_ID = "214678683422556160";


    /**
     * 出库状态 2已完成
     */
    private static final Integer OUT_STATUS_FINISH = 2;

    private static final String BILL_TYPE_THREE_OUT = "XGSC";
//    //履带吊crm 接口地址
//    @Value("${ld.crm.webservice.url}")
//    String ldCrmWebserviceUrl;

    @Autowired
    private PackageSpecService packageSpecService;

    @Autowired
    private ReceiptInService receiptInService;

    @Autowired
    private BarcodeManageMapper barcodeManageMapper;

    @Autowired
    private WarehouseInventoryService warehouseInventoryService;

    @Autowired
    private WarehouseDOMapper warehouseDOMapper;

    @Autowired
    private WarehouseDeliveryRecordMapper warehouseDeliveryRecordMapper;

    @Autowired
    private ReceiptInMapper receiptInMapper;

    @Autowired
    private WarehouseInboundRecordService warehouseInboundRecordService;

    @Autowired
    private ReceiptInDetailMapper receiptInDetailMapper;

    @Autowired
    private DeliveryNoteService deliveryNoteService;

    @Autowired
    private SaleIntentionService saleIntentionService;

    @Autowired
    private PubMaterialsMapper pubMaterialsMapper;

    @Autowired
    private WarehouseInboundRecordMapper warehouseInboundRecordMapper;

    @Autowired
    private WarehouseDeliveryRecordService warehouseDeliveryRecordService;


    /**
     * 到付
     */
    private static final String ARRIVED_PAY = "1";
    @Autowired
    private ExpressCodeInfoMapper expressCodeInfoMapper;

    @Autowired
    private WarehouseDeliveryMapper warehouseDeliveryMapper;

    @Autowired
    private PackageSpecDOMapper packageSpecDOMapper;

    @Value("${ns.delivery.restUrl:1}")
    private String deliveryUrl;

    @Value("${ns.auth.tokenId:1}")
    private String tokenId;

    @Value("${ns.auth.tokenSecret:1}")
    private String tokenSecret;

    @Value("${ns.auth.consumerKey:1}")
    private String consumerKey;

    @Value("${ns.auth.consumerSecret:1}")
    private String consumerSecret;

    @Value("${ns.auth.realm:1}")
    private String realm;

    public PageCommonVO outBillList(SearchCommonVO<OutBillParamVO> condition, String orgId, String departmentId) {
        PageCommonVO pageCommonVO = new PageCommonVO();
        switch (condition.getFilters().getBillType()) {
            case "XGFT"://发货通知单
                pageCommonVO = deliveryNote(condition.getPageNum(), condition.getPageSize(), condition.getFilters().getKeyWords(), orgId, condition.getFilters().getPurchaseOrgId(), condition.getFilters().getWarehouseCode(), departmentId, condition.getFilters().getQueryType());
                break;
            case "XGSC"://三包出库单
                pageCommonVO = threeOut(condition.getPageNum(), condition.getPageSize(), condition.getFilters().getKeyWords(), orgId, condition.getFilters().getPurchaseOrgId(), condition.getFilters().getSortClumn(), condition.getFilters().getSortMethod(), departmentId);
                break;
            case "XGQD"://区域调拨单
                pageCommonVO = regionAllot(condition.getPageNum(), condition.getPageSize(), condition.getFilters().getKeyWords(), orgId, departmentId);
                break;
            case "XGFC":
                pageCommonVO = abnormalOut(condition.getPageNum(), condition.getPageSize(), condition.getFilters().getKeyWords(), orgId, condition.getFilters().getPurchaseOrgId());
                break;
            case "XSCK":
                pageCommonVO = salesBillOut(condition.getPageNum(), condition.getPageSize(), condition.getFilters().getKeyWords(), orgId);
                break;
        }
        return pageCommonVO;
    }

    public PageCommonVO threeDayPlanBillList(SearchCommonVO<OutBillParamVO> condition, String orgId) {
        PageCommonVO pageCommonVO = new PageCommonVO();
        switch (condition.getFilters().getBillType()) {
            case "XGFT":
                pageCommonVO = threeDayPlanDlv(condition.getPageNum(), condition.getPageSize(), condition.getFilters().getKeyWords(), orgId, condition.getFilters().getPlanDate(), condition.getFilters().getPurchaseOrgId());
                break;
            case "XGSC":
                pageCommonVO = threeOutThreeDayPlan(condition.getPageNum(), condition.getPageSize(), condition.getFilters().getKeyWords(), orgId, condition.getFilters().getPlanDate(), condition.getFilters().getPurchaseOrgId());
                break;
        }
        return pageCommonVO;
    }

    public OutBillItemVO OutBillItem(String id, String billType) {
        switch (billType) {
            case "XGFT":
                return deliveryNoteItem(id);
            case "XGSC":
                return threeOutItem(id);
            case "XGQD":
                return regionAllot(id);
            case "XGFC":
                return abnormalOutItem(id);
            case "XSCK":
                return salesBillOutItem(id);
        }
        return null;
    }

    private OutBillItemVO salesBillOutItem(String id) {
        OutBillItemVO outBillItemVO = new OutBillItemVO();
        outBillItemVO.setBillType("XSCK");
        SalesOutBillDO salesOutBillDO = salesOutBillMapper.selectByPrimaryKey(id);
        if (null != salesOutBillDO) {

            SalesBillDO salesBillDO = salesBillMapper.selectBySalesBillNo(salesOutBillDO.getSalesBillNo());
            if (null != salesBillDO) {
                outBillItemVO.setPurchaseOrgId(salesBillDO.getClientId());
                outBillItemVO.setPurchaseOrgName(salesBillDO.getClientName());
            }
            CompanyInfoDO companyInfoDO = companyInfoMapper.item(salesOutBillDO.getOrgId());
            if (null != companyInfoDO) {
                outBillItemVO.setCreateCompanyName(companyInfoDO.getCompanyName());
                outBillItemVO.setSupplierOrgName(companyInfoDO.getCompanyName());
            }
            outBillItemVO.setAddress(salesOutBillDO.getReceiptAddress());
            outBillItemVO.setReceiverName(salesOutBillDO.getConsignee());
            outBillItemVO.setReceiverPhone(salesOutBillDO.getContactPhone());
            outBillItemVO.setDispatcherName(salesOutBillDO.getServicePersonName());

//            outBillItemVO.setReceiverFax(deliveryNoteDO.getReceiverFax());
//            outBillItemVO.setDeliveryTypeName(deliveryNoteDO.getDeliveryTypeName());
//            outBillItemVO.setAddressCode();
//            outBillItemVO.setSettleTypeId(deliveryNoteDO.getSettleTypeId());
//            outBillItemVO.setSettleTypeName(deliveryNoteDO.getSettleTypeName());
//            outBillItemVO.setShippingMethod(deliveryNoteDO.getDeliveryTypeName());
//            outBillItemVO.setShippingMethodId(deliveryNoteDO.getDeliveryTypeId());
//            outBillItemVO.setShippingSecondMethod(deliveryNoteDO.getSendTypeChildName());
//            outBillItemVO.setShippingSecondMethodId(deliveryNoteDO.getSendTypeChildId());
        }
        return outBillItemVO;
    }

    private OutBillItemVO regionAllot(String id) {
        OutBillItemVO outBillItemVO = new OutBillItemVO();
        outBillItemVO.setBillType("XGQD");
        RegionAllotDO regionAllotDO = regionAllotMapper.selectByPrimaryKey(id);
        if (regionAllotDO != null) {
            CompanyInfoDO companyInfoDO = companyInfoMapper.item(regionAllotDO.getOrgId());
            if (companyInfoDO != null) {
                outBillItemVO.setSupplierOrgName(companyInfoDO.getCompanyName());
                outBillItemVO.setCreateCompanyName(companyInfoDO.getCompanyName());
            }
            outBillItemVO.setAddress(regionAllotDO.getReceiveAddress());
            outBillItemVO.setDispatcherName(regionAllotDO.getCreateName());
            outBillItemVO.setReceiverName(regionAllotDO.getReceiveUser());
            outBillItemVO.setReceiverPhone(regionAllotDO.getReceiveTel());
        }
        return outBillItemVO;
    }

    public DeliveryReceiptInVO getMaterialsInfo(String id, String orgId) throws Exception {
        DeliveryReceiptDO deliveryReceiptDO = deliveryReceiptMapper.item(id);
        if (deliveryReceiptDO == null) {
            return null;
        }
        if (!deliveryReceiptDO.getDeliveryStatus().equals(DeliveryReceiptEnum.DeliveryStatus.Received.toString())) {
            return null;
        }
        if (deliveryReceiptDO.getIsDel().equals(0)) {
            return null;
        }
        DeliveryReceiptInVO deliveryReceiptInVO = new DeliveryReceiptInVO();
        deliveryReceiptInVO.setReceiptNo(deliveryReceiptDO.getBillNo());
        deliveryReceiptInVO.setReceiptId(deliveryReceiptDO.getId());
        List<DeliveryReceiptInDetailVO> detailVOS = new ArrayList<>();
        List<BoxupDetailDO> boxupDetailDOS = boxupMainService.boxDetailAmount(id);
        for (BoxupDetailDO boxupDetailDO : boxupDetailDOS
        ) {
            //判断基础表里是否有此零件，如果没有就新增
            PriMaterialsDO priMaterialsDO = priMaterialsMapper.itemByNo(boxupDetailDO.getMaterialsNo(), orgId);
            if (priMaterialsDO == null) {
                PriMaterialsDO newPriMaterialsDO = priMaterialsMapper.itemByNo(boxupDetailDO.getMaterialsNo(), deliveryReceiptDO.getOrgId());
                if (newPriMaterialsDO == null) {
                    throw new Exception("供应商基础零件中未找到此零件，" + boxupDetailDO.getMaterialsNo());
                }
                priMaterialsDO = new PriMaterialsDO();
                BeanUtils.copyProperties(newPriMaterialsDO, priMaterialsDO);
                priMaterialsDO.setStockLocation(null);
                priMaterialsDO.setOrgId(orgId);
                priMaterialsDO.setStandardPrice(new BigDecimal("0"));
                boolean success = priMaterialsMapper.insert(priMaterialsDO) > 0;
                if (!success) {
                    throw new Exception("向基础零件中新增此零件失败，" + boxupDetailDO.getMaterialsNo());
                }
            }
            DeliveryReceiptInDetailVO deliveryReceiptInDetailVO = new DeliveryReceiptInDetailVO();
            deliveryReceiptInDetailVO.setMaterialsNo(priMaterialsDO.getMaterialsNo());
            deliveryReceiptInDetailVO.setMaterialsDes(priMaterialsDO.getMaterialsDes());
            deliveryReceiptInDetailVO.setMaterialsType(priMaterialsDO.getMaterialsType());
            deliveryReceiptInDetailVO.setQty(boxupDetailDO.getQty());
            deliveryReceiptInDetailVO.setUnit(priMaterialsDO.getUnit());
            detailVOS.add(deliveryReceiptInDetailVO);
        }
        deliveryReceiptInVO.setDetailVOList(detailVOS);
        return deliveryReceiptInVO;
    }

    @Transactional(rollbackFor = Exception.class)
    public ErrorCode inStorage(DeliveryReceiptInVO deliveryReceiptInVO, String orgId, String userId) throws Exception {
        AbnormalInDO abnormalInDO = getAbnormalInDO(deliveryReceiptInVO, orgId, userId);
        if (abnormalInDO == null) {
            return ErrorCode.IllegalArument;
        }
        boolean success = abnormalInMapper.insert(abnormalInDO) > 0;
        if (!success) {
            return ErrorCode.Failure;
        }
        List<DeliveryReceiptInDetailVO> detailVOList = deliveryReceiptInVO.getDetailVOList();
        if (!CollectionUtils.isNotEmpty(detailVOList)) {
            throw new Exception("无零件详情");
        }
        BigDecimal allAmount = BigDecimal.ZERO;
        WarehouseInboundDO warehouseInboundDO = getWarehouseInboundDO(abnormalInDO, orgId, allAmount);
        if (warehouseInboundDO == null) {
            return ErrorCode.IllegalArument;
        }
        for (DeliveryReceiptInDetailVO detail : detailVOList) {
            boolean inQty = true;
            if (StringUtil.isEmpty(detail.getLocationCode())) {
                inQty = false;
            }
            Map<String, Object> warehouseMap = warehouseAreaLocationDOMapper.findAllCode(detail.getLocationCode(), orgId);
            if (warehouseMap == null) {
                inQty = false;
            }
            if (!deliveryReceiptInVO.getInLocation().equals(warehouseMap.get("WAREHOUSE_CODE")) || !deliveryReceiptInVO.getInArea().equals(warehouseMap.get("AREA_CODE"))) {
                inQty = false;
            }
            AbnormalInDetailDO abnormalInDetailDO = getDetailDO(detail, orgId, userId, abnormalInDO.getAbnormalNo(), inQty);
            if (abnormalInDetailDO == null) {
                throw new Exception("获取id失败");
            }
            allAmount = allAmount.add(abnormalInDetailDO.getQty());
            WarehouseInboundDetailDO warehouseInboundDetailDO = getWarehouseInboundDetailDO(warehouseInboundDO, detail, inQty);
            if (warehouseInboundDetailDO == null) {
                throw new Exception("获取id失败");
            }
            abnormalInDetailMapper.insert(abnormalInDetailDO);
            warehouseInboundDetailMapper.insert(warehouseInboundDetailDO);
        }
        warehouseInboundDO.setAmount(allAmount);
        abnormalInMapper.insert(abnormalInDO);
        warehouseInboundMapper.insert(warehouseInboundDO);
        return ErrorCode.Success;
    }

    private AbnormalInDO getAbnormalInDO(DeliveryReceiptInVO deliveryReceiptInVO, String orgId, String userId) {
        ActionResult<String> textResult = fastGenClient.textGuid();
        if (textResult.getCode() != ErrorCode.Success.getCode()) {
            return null;
        }
        AbnormalInDO abnormalInDO = new AbnormalInDO();
        BeanUtils.copyProperties(deliveryReceiptInVO, abnormalInDO);
        abnormalInDO.setId(textResult.getValue());
        abnormalInDO.setAbnormalNo(genDocumentService.getDocumentNo(BillDesc.AbnoramlIn));
        abnormalInDO.setState(2);
        abnormalInDO.setApplicationDate(new Date());
        abnormalInDO.setOrgId(orgId);
        abnormalInDO.setReceiptNo(deliveryReceiptInVO.getReceiptNo());
        abnormalInDO.setCreateId(userId);
        abnormalInDO.setCreateName(commonService.getUserName(userId));

        BillTypeConfigVO config = billTypeConfigService.findByPK(deliveryReceiptInVO.getTypeId());
        if (config != null) {
            abnormalInDO.setIsSynsap(config.getIsSynsap());
            abnormalInDO.setType(config.getType());
            abnormalInDO.setMoveType(config.getMoveType());
        } else {
            abnormalInDO.setIsSynsap(0);
        }
        return abnormalInDO;
    }

    private AbnormalInDetailDO getDetailDO(DeliveryReceiptInDetailVO detail, String orgId, String userId, String abnormalNo, boolean inQty) {
        AbnormalInDetailDO abnormalInDetailDO = new AbnormalInDetailDO();
        ActionResult<String> textResult = fastGenClient.textGuid();
        if (textResult.getCode() != ErrorCode.Success.getCode()) {
            return null;
        }
        abnormalInDetailDO.setId(textResult.getValue());
        abnormalInDetailDO.setAbnormalNo(abnormalNo);
        abnormalInDetailDO.setMaterialsNo(detail.getMaterialsNo());
        abnormalInDetailDO.setMaterialsDes(detail.getMaterialsDes());
        abnormalInDetailDO.setMaterialsType(detail.getMaterialsType());
        abnormalInDetailDO.setUnit(detail.getUnit());
        abnormalInDetailDO.setQty(detail.getQty());
        if (inQty) {
            abnormalInDetailDO.setRealQty(detail.getQty());
            abnormalInDetailDO.setState(2);
            abnormalInDetailDO.setPrintNum(detail.getQty());
        } else {
            abnormalInDetailDO.setRealQty(new BigDecimal("0"));
            abnormalInDetailDO.setState(0);
            abnormalInDetailDO.setPrintNum(new BigDecimal("0"));
        }
        abnormalInDetailDO.setOrgId(orgId);
        abnormalInDetailDO.setCreateId(userId);
        abnormalInDetailDO.setCreateDate(new Date());
        return abnormalInDetailDO;
    }

    private WarehouseInboundDO getWarehouseInboundDO(AbnormalInDO abnormalInDO, String orgId, BigDecimal allAmount)
            throws Exception {
        ActionResult<String> textResult = fastGenClient.textGuid();
        if (textResult.getCode() != ErrorCode.Success.getCode()) {
            return null;
        }
        WarehouseInboundDO warehouseInboundDO = new WarehouseInboundDO();
        warehouseInboundDO.setId(textResult.getValue());
        warehouseInboundDO.setInboundOrder(genDocumentService.genDocumentNo(BillDesc.InputNo, orgId));
        warehouseInboundDO.setOrgId(orgId);
        warehouseInboundDO.setBusinessSingle("XGFR");
        warehouseInboundDO.setBusinessOrder(abnormalInDO.getAbnormalNo());
        warehouseInboundDO.setWarehouseCode(abnormalInDO.getInLocation());
        warehouseInboundDO.setAmount(allAmount);
        warehouseInboundDO.setTotalPrice(new BigDecimal("0"));
        warehouseInboundDO.setStatus(2);
        warehouseInboundDO.setNote("");
        warehouseInboundDO.setCreaterId(abnormalInDO.getCreateId());
        warehouseInboundDO.setCreateDate(new Date());
        warehouseInboundDO.setCreaterName(abnormalInDO.getCreateName());
        warehouseInboundDO.setInArea(abnormalInDO.getInArea());
        warehouseInboundDO.setSapInArea("");
        return warehouseInboundDO;
    }

    private WarehouseInboundDetailDO getWarehouseInboundDetailDO(WarehouseInboundDO warehouseInboundDO, DeliveryReceiptInDetailVO detail, boolean inQty) {
        ActionResult<String> textResult = fastGenClient.textGuid();
        if (textResult.getCode() != ErrorCode.Success.getCode()) {
            return null;
        }
        WarehouseInboundDetailDO warehouseInboundDetailDO = new WarehouseInboundDetailDO();
        warehouseInboundDetailDO.setId(textResult.getValue());
        warehouseInboundDetailDO.setInboundOrder(warehouseInboundDO.getInboundOrder());
        warehouseInboundDetailDO.setOrgId(warehouseInboundDO.getOrgId());
        warehouseInboundDetailDO.setBusinessOrder(warehouseInboundDO.getBusinessOrder());
        warehouseInboundDetailDO.setBusinessSingle("XGFR");
        warehouseInboundDetailDO.setMaterialNo(detail.getMaterialsNo());
        warehouseInboundDetailDO.setMaterialName(detail.getMaterialsDes());
        warehouseInboundDetailDO.setMaterialType(detail.getMaterialsType());
        warehouseInboundDetailDO.setAmount(detail.getQty());

        warehouseInboundDetailDO.setTotalPrice(new BigDecimal("0"));
        warehouseInboundDetailDO.setUnit(detail.getUnit());
        if (inQty) {
            warehouseInboundDetailDO.setStatus(2);
            warehouseInboundDetailDO.setRealAmount(detail.getQty());
            warehouseInboundDetailDO.setPrintNum(detail.getQty());
            warehouseInboundDetailDO.setPrintState(2);
        } else {
            warehouseInboundDetailDO.setStatus(0);
            warehouseInboundDetailDO.setRealAmount(new BigDecimal("0"));
            warehouseInboundDetailDO.setPrintNum(new BigDecimal("0"));
            warehouseInboundDetailDO.setPrintState(0);
        }
        warehouseInboundDetailDO.setCreaterId(warehouseInboundDO.getCreaterId());
        warehouseInboundDetailDO.setCreaterName(warehouseInboundDO.getCreaterName());
        warehouseInboundDetailDO.setCreateDate(new Date());


        return warehouseInboundDetailDO;
    }


    private OutBillItemVO threeOutItem(String id) {
        OutBillItemVO outBillItemVO = new OutBillItemVO();
        outBillItemVO.setBillType("XGSC");
        ThreeGuaranteesOutDO threeGuaranteesOutDO = threeGuaranteesOutMapper.item(id);
        if (threeGuaranteesOutDO != null) {
            CompanyInfoDO companyInfoDO = companyInfoMapper.item(threeGuaranteesOutDO.getOrgId());
            if (companyInfoDO != null) {
                outBillItemVO.setSupplierOrgName(companyInfoDO.getCompanyName());
                outBillItemVO.setCreateCompanyName(companyInfoDO.getCompanyName());
            }
            outBillItemVO.setSettleTypeName(threeGuaranteesOutDO.getSettleTypeName());
            outBillItemVO.setSettleTypeId(threeGuaranteesOutDO.getSettleTypeId());
            outBillItemVO.setReceiverPhone(threeGuaranteesOutDO.getReceiverPhone());
            outBillItemVO.setReceiverName(threeGuaranteesOutDO.getReceiverName());
            outBillItemVO.setReceiverFax(threeGuaranteesOutDO.getReceiverFax());
            outBillItemVO.setPurchaseOrgName(threeGuaranteesOutDO.getPurchaseOrgName());
            outBillItemVO.setPurchaseOrgId(threeGuaranteesOutDO.getPurchaseOrgId());
            outBillItemVO.setDeliveryTypeName(threeGuaranteesOutDO.getDeliveryTypeName());
            outBillItemVO.setAddress(threeGuaranteesOutDO.getAddress());
            outBillItemVO.setDispatcherName(threeGuaranteesOutDO.getCreateName());
            outBillItemVO.setShippingMethod(threeGuaranteesOutDO.getDeliveryTypeName());
            outBillItemVO.setShippingMethodId(threeGuaranteesOutDO.getDeliveryTypeId());
            outBillItemVO.setShippingSecondMethod(threeGuaranteesOutDO.getSendTypeChildName());
            outBillItemVO.setShippingSecondMethodId(threeGuaranteesOutDO.getSendTypeChildId());
            outBillItemVO.setServiceSite(threeGuaranteesOutDO.getServiceSite());
            outBillItemVO.setServiceName(threeGuaranteesOutDO.getServiceName());
        }
        return outBillItemVO;
    }

    private OutBillItemVO deliveryNoteItem(String id) {
        OutBillItemVO outBillItemVO = new OutBillItemVO();
        outBillItemVO.setBillType("XGFT");
        DeliveryNoteDO deliveryNoteDO = deliveryNoteMapper.item(id);
        if (deliveryNoteDO != null) {
            outBillItemVO.setAddress(deliveryNoteDO.getAddress());
            outBillItemVO.setAddressCode(deliveryNoteDO.getAddressCode());
            outBillItemVO.setCreateCompanyName(deliveryNoteDO.getCreateCompanyName());
            outBillItemVO.setDeliveryTypeName(deliveryNoteDO.getDeliveryTypeName());
            outBillItemVO.setPurchaseOrgId(deliveryNoteDO.getPurchaseOrgId());
            outBillItemVO.setPurchaseOrgName(deliveryNoteDO.getPurchaseOrgName());
            outBillItemVO.setReceiverFax(deliveryNoteDO.getReceiverFax());
            outBillItemVO.setReceiverName(deliveryNoteDO.getReceiverName());
            outBillItemVO.setReceiverPhone(deliveryNoteDO.getReceiverPhone());
            outBillItemVO.setSettleTypeId(deliveryNoteDO.getSettleTypeId());
            outBillItemVO.setSettleTypeName(deliveryNoteDO.getSettleTypeName());
            outBillItemVO.setSupplierOrgName(deliveryNoteDO.getSupplierOrgName());
            outBillItemVO.setDispatcherName(deliveryNoteDO.getCreateName());
            outBillItemVO.setShippingMethod(deliveryNoteDO.getDeliveryTypeName());
            outBillItemVO.setShippingMethodId(deliveryNoteDO.getDeliveryTypeId());
            outBillItemVO.setShippingSecondMethod(deliveryNoteDO.getSendTypeChildName());
            outBillItemVO.setShippingSecondMethodId(deliveryNoteDO.getSendTypeChildId());
            outBillItemVO.setPurchaseContractNo(deliveryNoteDO.getPurchaseContractNo());
            outBillItemVO.setDeliveryDate(deliveryNoteDO.getDeliveryDate());
            outBillItemVO.setCountry(deliveryNoteDO.getCountry());
        }
        return outBillItemVO;
    }

    private OutBillItemVO abnormalOutItem(String id) {
        OutBillItemVO outBillItemVO = new OutBillItemVO();
        outBillItemVO.setBillType("XGFC");
        AbnormalOutDO abnormalOutDO = abnormalOutMapper.item(id);
        if (abnormalOutDO != null) {
            outBillItemVO.setAddress(abnormalOutDO.getAddress());
            //outBillItemVO.setCreateCompanyName(abnormalOutDO.get());
            outBillItemVO.setDeliveryTypeName(abnormalOutDO.getDeliveryTypeName());
            outBillItemVO.setPurchaseOrgId(abnormalOutDO.getAgentOrgId());
            outBillItemVO.setPurchaseOrgName(abnormalOutDO.getAgentName());
            outBillItemVO.setReceiverFax(abnormalOutDO.getReceiverFax());
            outBillItemVO.setReceiverName(abnormalOutDO.getReceiverName());
            outBillItemVO.setReceiverPhone(abnormalOutDO.getReceiverPhone());
            outBillItemVO.setSettleTypeId(abnormalOutDO.getSettleTypeId());
            outBillItemVO.setSettleTypeName(abnormalOutDO.getSettleTypeName());
            //outBillItemVO.setSupplierOrgName(abnormalOutDO.getSupplierOrgName());
            outBillItemVO.setDispatcherName(abnormalOutDO.getCreateName());
            outBillItemVO.setShippingMethod(abnormalOutDO.getDeliveryTypeName());
            outBillItemVO.setShippingMethodId(abnormalOutDO.getDeliveryTypeId());
            outBillItemVO.setShippingSecondMethod(abnormalOutDO.getSendTypeChildName());
            outBillItemVO.setShippingSecondMethodId(abnormalOutDO.getSendTypeChildId());
            outBillItemVO.setCarrier(abnormalOutDO.getLogistics());
            outBillItemVO.setCarrierPerson(abnormalOutDO.getLogisticsPerson());
        }
        return outBillItemVO;
    }

    private PageCommonVO regionAllot(int pageNum, int pageSize, String keyWords, String orgId, String departmentId) {
        PageCommonVO result = new PageCommonVO();
        WareHousePermission wareHousePermission = relationService.wareHouseChoicePermit(orgId, departmentId);
        if (!wareHousePermission.isHasPermission()) {
            result.setPageInfo(new PageInfo(Collections.EMPTY_LIST));
            result.setPageInfoList(Collections.EMPTY_LIST);
            return result;
        }
        List<String> permissionWarehouses = wareHousePermission.getPermissionWarehouses();
        RegionAllotVO condition = new RegionAllotVO();
        condition.setOrgId(orgId);
        condition.setAllotOrder(keyWords);
        condition.setBillStatus("2");
        condition.setWarehousePermitList(permissionWarehouses);
        boolean couldRegionAllotDulSelect = couldRegionAllotDulSelect(orgId);
        PageHelperPlus.orderBy("create_date desc");
        PageHelperPlus.startPage(pageNum, pageSize);
        List<RegionAllotDO> doList;
        if (!couldRegionAllotDulSelect) {
            doList = regionAllotMapper.listNotBeCreatedDeliveryReceipt(condition);
        } else {
            doList = regionAllotMapper.list(condition);
        }
        List<OutBillValuesVO> voList = new ArrayList<>();
        for (RegionAllotDO entity : doList) {
            OutBillValuesVO model = new OutBillValuesVO();
            model.setBillType("XGQD");
            model.setCreateDate(entity.getCreateDate());
            model.setCreateName(entity.getCreateName());
            model.setCreatorId(entity.getCreateId());
            model.setDeliveryNo(entity.getAllotOrder());
            model.setAddress(entity.getReceiveAddress());
            model.setId(entity.getId());
            model.setStatus(entity.getOutState() == null ? null : entity.getOutState().toString());
            voList.add(model);
        }
        result.setPageInfo(new PageInfo(doList));
        result.setPageInfoList(voList);
        return result;
    }

    //  判断传入的公司同一个业务单据是否可以被多次选择创建发运交接单，如果可以则返回true,否则返回false
    private boolean couldRegionAllotDulSelect(String orgId) {
        if (StringUtils.isEmpty(orgId)) {
            return true;
        }
        CompanyInfoDO companyInfo = companyInfoMapper.item(orgId);
        if (companyInfo == null) {
            return true;
        }
        String sapCode = companyInfo.getSapCode();
        //随车的才拦截不能重复被选择创建
        if (CompanyUtil.isSCSapCode(sapCode)) {
            return false;
        }
        return true;
    }

    private PageCommonVO threeOut(int pageNum, int pageSize, String keyWords, String orgId, String purchaseOrgId, String sortColumn, String sortMethod, String departmentId) {
        PageCommonVO result = new PageCommonVO();
        WareHousePermission wareHousePermission = relationService.wareHouseChoicePermit(orgId, departmentId);
        if (!wareHousePermission.isHasPermission()) {
            result.setPageInfo(new PageInfo(Collections.EMPTY_LIST));
            result.setPageInfoList(Collections.EMPTY_LIST);
            return result;
        }
        //出库单如果已经进行了新增发货运单操作，则不能再被查询到，原来只针对塔机，现在加入随车===modify by  wangzhaoyu
        String sapCode = companyInfoMapper.getSapCodeByOrgId(orgId);
        ThreeGuaranteesOutVO condition = new ThreeGuaranteesOutVO();
        condition.setOrgId(orgId);
        condition.setKeyWords(keyWords);
        condition.setPurchaseOrgId(purchaseOrgId);
        condition.setSortClumn(sortColumn);
        condition.setSortMethod(sortMethod);
        List<String> permissionWarehouses = wareHousePermission.getPermissionWarehouses();
        condition.setWarehousePermitList(permissionWarehouses);
        PageHelperPlus.orderBy("create_date desc");
        PageHelperPlus.startPage(pageNum, pageSize);
        List<ThreeGuaranteesOutDO> doList;
        if (!threeGuaranteesCouldDulp(orgId, sapCode)) {//业务上不允许重复出现单据
            String sortStr = threeGuarantOutQuerySort(sortColumn, sortMethod);
            if (!StringUtils.isEmpty(sortStr)) {
                PageHelperPlus.orderBy(sortStr);
            }
            doList = threeGuaranteesOutMapper.listForWJ(condition);
        } else {
            doList = threeGuaranteesOutMapper.list(condition);
        }
        List<OutBillValuesVO> voList = new ArrayList<>();
        for (ThreeGuaranteesOutDO entity : doList) {
            OutBillValuesVO model = new OutBillValuesVO();
            model.setBillType("XGSC");
            model.setCreateDate(entity.getCreateDate());
            model.setCreateName(entity.getCreateName());
            model.setCreatorId(entity.getCreateId());
            model.setDeliveryNo(entity.getGuaranteesOutNo());
            model.setId(entity.getId());
            //model.setPurchaseNo(entity.getPurchaseNo());
            model.setPurchaseOrgId(entity.getPurchaseOrgId());
            model.setPurchaseOrgName(entity.getPurchaseOrgName());
            model.setSaleNo(entity.getPurchaseNo());
            model.setNote(entity.getNote());
            model.setAddress(entity.getAddress());
            model.setPurchaseLevel("紧急");
            model.setServiceSite(entity.getServiceSite());
            model.setServiceName(entity.getServiceName());
            model.setProdType(entity.getProdType());
            model.setMachineNumber(entity.getMachineNumber());
            model.setCrmOrder(entity.getCrmOrder());
            model.setServiceNo(entity.getServiceNo());
            model.setStatus(entity.getOutLocationStatus() == null ? null : entity.getOutLocationStatus().toString());
            voList.add(model);
        }
        result.setPageInfo(new PageInfo(doList));
        result.setPageInfoList(voList);
        return result;
    }


    //判断当前操作发运交接单的公司，三包出库单在业务上是否允许重复出现，返回false表示不能重复
    private boolean threeGuaranteesCouldDulp(String orgId, String sapCode) {
        if (StringUtils.isEmpty(orgId) || StringUtils.isEmpty(sapCode)) {
            return true;
        }
        if (CompanyUtil.isWJ(orgId) || CompanyUtil.isSCSapCode(sapCode) || CompanyUtil.isLvdaiSapCode(sapCode)) {
            return false;
        }
        return true;
    }

    /**
     * 三包出库查询，自定义排序拼接，目前是服务单号排序
     */
    private String threeGuarantOutQuerySort(String sortColumn, String sortMethod) {
        StringBuffer resultSb = new StringBuffer();
        if (!StringUtils.isEmpty(sortColumn) && !StringUtils.isEmpty(sortMethod)) {
            if ("serviceNo".equals(sortColumn)) {
                resultSb.append("tgp.service_no");
            }
            if (resultSb.length() > 0 && "asc".equals(sortMethod.toLowerCase()) || "desc".equals(sortMethod.toLowerCase())) {
                resultSb.append(" ");
                resultSb.append(sortMethod);
            }
        }
        return resultSb.toString();
    }

    //三日计划交货单查询
    private PageCommonVO threeDayPlanDlv(int pageNum, int pageSize, String keyWords, String orgId, Date planDate, String purchaseOrgId) {
        DlvInfoQueryVO condition = new DlvInfoQueryVO();
        condition.setOrgId(orgId);
        condition.setKeyWords(keyWords);
        condition.setPlanDate(DateUtil.formatDate(planDate));
        condition.setPurchaseOrgId(purchaseOrgId);
        PageCommonVO result = new PageCommonVO();
        PageHelperPlus.orderBy("id desc");
        PageHelperPlus.startPage(pageNum, pageSize);
        List<OutBillValuesVO> doList = threeDayPlanDetailDOMapper.threeDayPlanDlv(condition);
        List<OutBillValuesVO> voList = new ArrayList<>();
        for (OutBillValuesVO entity : doList) {
            OutBillValuesVO model = new OutBillValuesVO();
            BeanUtils.copyProperties(entity, model);
            DeliveryNoteDO deliveryNoteDO = new DeliveryNoteDO();
            deliveryNoteDO.setPurchaseLevelName(model.getPurchaseLevelName());
            deliveryNoteDO.setSendTypeChildName(model.getSendTypeChildName());
            model.setPurchaseLevel(getPurchaseLevel(deliveryNoteDO));
            model.setAddress(StringUtil.isEmpty(entity.getAddressCode()) ? entity.getAddress() : entity.getAddressCode());
            voList.add(model);
        }
        result.setPageInfo(new PageInfo(doList));
        result.setPageInfoList(voList);
        return result;
    }

    //三日计划三包单
    private PageCommonVO threeOutThreeDayPlan(int pageNum, int pageSize, String keyWords, String orgId, Date planDate, String purchaseOrgId) {
        DlvInfoQueryVO condition = new DlvInfoQueryVO();
        condition.setOrgId(orgId);
        condition.setKeyWords(keyWords);
        condition.setPlanDate(DateUtil.formatDate(planDate));
        condition.setPurchaseOrgId(purchaseOrgId);
        PageCommonVO result = new PageCommonVO();
        PageHelperPlus.orderBy("id desc");
        PageHelperPlus.startPage(pageNum, pageSize);
        List<OutBillValuesVO> doList = threeDayPlanDetailDOMapper.threeOutThreeDayPlan(condition);
        List<OutBillValuesVO> voList = new ArrayList<>();
        for (OutBillValuesVO entity : doList) {
            OutBillValuesVO model = new OutBillValuesVO();
            BeanUtils.copyProperties(entity, model);
            model.setPurchaseLevel("月度");
            voList.add(model);
        }
        result.setPageInfo(new PageInfo(doList));
        result.setPageInfoList(voList);
        return result;
    }

    private PageCommonVO deliveryNote(int pageNum, int pageSize, String keyWords, String orgId, String purchaseOrgId, String warehouseCode, String departmentId, Integer queryType) {
        PageCommonVO result = new PageCommonVO();
        WareHousePermission wareHousePermission = relationService.wareHouseChoicePermit(orgId, departmentId);
        if (!wareHousePermission.isHasPermission()) {
            result.setPageInfo(new PageInfo(Collections.EMPTY_LIST));
            result.setPageInfoList(Collections.EMPTY_LIST);
            return result;
        }
        List<String> permissionWarehouses = wareHousePermission.getPermissionWarehouses();
        DeliveryNoteVO deliveryNoteVO = new DeliveryNoteVO();
        deliveryNoteVO.setSupplierOrgId(orgId);
        deliveryNoteVO.setKeyWords(keyWords);
        deliveryNoteVO.setPurchaseOrgId(purchaseOrgId);
        deliveryNoteVO.setStatus("1");
        deliveryNoteVO.setOutLocation(warehouseCode);
        deliveryNoteVO.setWarehousePermitList(permissionWarehouses);
        //PageHelperPlus.orderBy("purchase_org_id asc, create_date desc");
        PageHelperPlus.orderBy("create_date desc");
        PageHelperPlus.startPage(pageNum, pageSize);
        List<DeliveryNoteDO> doList;
        if (CompanyUtil.isWJ(orgId)) {
            doList = deliveryNoteMapper.listForWJ(orgId, keyWords, warehouseCode, permissionWarehouses);
        } else {
            deliveryNoteVO.setQueryType(queryType);
            doList = deliveryNoteMapper.list(deliveryNoteVO);
        }
        List<OutBillValuesVO> voList = new ArrayList<>();
        for (DeliveryNoteDO entity : doList) {
            OutBillValuesVO model = new OutBillValuesVO();
            model.setBillType("XGFT");
            model.setCreateDate(entity.getCreateDate());
            model.setCreateName(entity.getCreateName());
            model.setCreatorId(entity.getCreatorId());
            model.setDeliveryNo(entity.getDeliveryNo());
            model.setId(entity.getId());
            model.setPurchaseNo(entity.getPurchaseNo());
            model.setPurchaseOrgId(entity.getPurchaseOrgId());
            model.setPurchaseOrgName(entity.getPurchaseOrgName());
            model.setSaleNo(entity.getSaleNo());
            model.setNote(entity.getNote());
            model.setCountry(entity.getCountry());
            model.setPurchaseLevel(getPurchaseLevel(entity));
            model.setAddress(StringUtil.isEmpty(entity.getAddressCode()) ? entity.getAddress() : entity.getAddressCode());
            model.setStatus(entity.getIsOut());
            voList.add(model);
        }
        result.setPageInfo(new PageInfo(doList));
        result.setPageInfoList(voList);
        return result;
    }

    private String getPurchaseLevel(DeliveryNoteDO noteDO) {
        StringBuilder sb = new StringBuilder(StringUtil.getString(noteDO.getPurchaseLevelName()));
        if (StringUtil.isNotEmpty(noteDO.getSendTypeChildName())) {
            sb.append("-").append(noteDO.getSendTypeChildName());
        }
        return sb.toString();
    }

    private PageCommonVO abnormalOut(int pageNum, int pageSize, String keyWords, String orgId, String purchaseOrgId) {
        AbnormalOutVO abnormalOutVO = new AbnormalOutVO();
        abnormalOutVO.setOrgId(orgId);
        abnormalOutVO.setKeyWords(keyWords);
        abnormalOutVO.setAgentOrgId(purchaseOrgId);
        boolean abnormalOutCouldDulSelect = abnormalOutCouldDulSelect(orgId);
        PageCommonVO result = new PageCommonVO();
        PageHelperPlus.orderBy("APPLICATION_DATE desc");
        PageHelperPlus.startPage(pageNum, pageSize);
        List<AbnormalOutDO> doList;
        if (!abnormalOutCouldDulSelect) {
            doList = abnormalOutMapper.listNotBeCreatedDeliveryReceipt(abnormalOutVO);
        } else {
            doList = abnormalOutMapper.list(abnormalOutVO);
        }
        List<OutBillValuesVO> voList = new ArrayList<>();
        for (AbnormalOutDO entity : doList) {
            OutBillValuesVO model = new OutBillValuesVO();
            model.setBillType("XGFC");
            model.setCreateDate(entity.getApplicationDate());
            model.setCreateName(entity.getCreateName());
            model.setCreatorId(entity.getCreateId());
            model.setDeliveryNo(entity.getAbnormalNo());
            model.setId(entity.getId());
            model.setPurchaseOrgId(entity.getAgentOrgId());
            model.setPurchaseOrgName(entity.getAgentName());
            model.setAddress(entity.getAddress());
            model.setNote(entity.getNote());
            model.setCarrier(entity.getLogistics());
            model.setCarrierPerson(entity.getLogisticsPerson());
            model.setStatus(entity.getStatus() == null ? null : entity.getStatus().toString());
            voList.add(model);
        }
        result.setPageInfo(new PageInfo(doList));
        result.setPageInfoList(voList);
        return result;
    }

    /**
     * @Des 其它出库单是否可以被重新选择，如果可以被重复选择发挥true,否则返回false
     * @Date 2021/5/11 14:20
     * @Author wangzhaoyu
     * @Param [orgId]
     * @Return boolean
     */
    private boolean abnormalOutCouldDulSelect(String orgId) {
        if (StringUtils.isEmpty(orgId)) {
            return true;
        }
        CompanyInfoDO companyInfo = companyInfoMapper.item(orgId);
        if (companyInfo == null) {
            return true;
        }
        String sapCode = companyInfo.getSapCode();
        //随车的才拦截不能重复被选择创建
        if (CompanyUtil.isSCSapCode(sapCode)) {
            return false;
        }
        return true;
    }


    private PageCommonVO salesBillOut(int pageNum, int pageSize, String keyWords, String orgId) {
        CompanyInfoDO companyInfoDO = companyInfoMapper.item(orgId);
        // 施维英支持销售赠送出库创建运单
        if (!CompanyUtil.isSWY(companyInfoDO.getSapCode())) {
            return new PageCommonVO();
        }

        SalesOutBillVO salesOutBillVO = new SalesOutBillVO();
        salesOutBillVO.setOrgId(orgId);
        salesOutBillVO.setKeyWords(keyWords);
//        salesOutBillVO.setAgentOrgId(purchaseOrgId);
        PageCommonVO result = new PageCommonVO();
        PageHelperPlus.orderBy("CREATE_DATE desc");
        PageHelperPlus.startPage(pageNum, pageSize);
        List<SalesOutBillDO> doList = salesOutBillMapper.list(salesOutBillVO);
        List<OutBillValuesVO> voList = new ArrayList<>();
        for (SalesOutBillDO entity : doList) {
            OutBillValuesVO model = new OutBillValuesVO();
            SalesBillDO salesBillDO = salesBillMapper.selectBySalesBillNo(entity.getSalesBillNo());
            model.setBillType("XSCK");
            model.setCreateDate(entity.getCreateDate());
            model.setCreateName(commonService.getUserName(entity.getCreateId()));
            model.setCreatorId(entity.getCreateId());
            model.setDeliveryNo(entity.getSalesOutBillNo());
            model.setId(entity.getId());
            model.setPurchaseOrgId(salesBillDO.getClientId());
            model.setPurchaseOrgName(salesBillDO.getClientName());
            model.setNote(entity.getRemark());
            voList.add(model);
        }
        result.setPageInfo(new PageInfo(doList));
        result.setPageInfoList(voList);
        return result;
    }

    public PageCommonVO list(SearchCommonVO<DeliveryReceiptQueryParam> condition, String orgId, String deptId, String userId) throws Exception {
        PageCommonVO pageCommonVO = new PageCommonVO();
        //获取仓库配置权限
        WareHousePermission wareHousePermission = relationService.hasMajorWareHousePermission(orgId, deptId);

        UserDetailDTO userInfo = authClient.getUserDetail(userId).getValue();
        //当前用户是服务人员
        if (StringUtil.isNotEmpty(userInfo.getIsService()) && "1".equals(userInfo.getIsService())) {
            condition.getFilters().setServiceName(userInfo.getName());
        } else if (!wareHousePermission.isHasPermission()) {
            pageCommonVO.setPageInfo(new PageInfo(new ArrayList()));
            pageCommonVO.setPageInfoList(new ArrayList<>());
            return pageCommonVO;
        } else {
            condition.getFilters().setWarehousePermitList(wareHousePermission.getPermissionWarehouses());
        }

        PageHelperPlus.orderBy("create_date desc");
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        condition.getFilters().setBillNosList(xcmg.device.infra.StringUtil.splitList(condition.getFilters().getBillNos()));
        List<DeliveryReceiptDO> doList = deliveryReceiptMapper.listWarehousePermit(condition.getFilters());
        List<DeliveryReceiptVO> voList = new ArrayList<>();
        for (DeliveryReceiptDO deliveryReceiptDO : doList
        ) {
            DeliveryReceiptVO deliveryReceiptVO = new DeliveryReceiptVO();
            BeanUtils.copyProperties(deliveryReceiptDO, deliveryReceiptVO);
            int recordCount = deliveryReceiptLogisticsMapper.countByDate(deliveryReceiptDO.getBillNo(), org.apache.commons.lang3.time.DateFormatUtils.format(new Date(), "yyyyMMdd"));
            deliveryReceiptVO.setRecordFlag(recordCount > 0 ? DeliveryReceiptVO.RECORD_FLAG_YES : DeliveryReceiptVO.RECORD_FLAG_NO);
            deliveryReceiptVO.setPurchaseLevel(getPurchaseLevel(deliveryReceiptDO.getId()));
            voList.add(deliveryReceiptVO);
        }
        pageCommonVO.setPageInfo(new PageInfo(doList));
        pageCommonVO.setPageInfoList(voList);
        return pageCommonVO;
    }

    public PageCommonVO listAll(SearchCommonVO<DeliveryReceiptVO> condition) {
        PageCommonVO pageCommonVO = new PageCommonVO();
        PageHelperPlus.orderBy("create_date desc");
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        List<DeliveryReceiptDO> doList = deliveryReceiptMapper.listAll(condition.getFilters());
        List<DeliveryReceiptVO> voList = new ArrayList<>();
        for (DeliveryReceiptDO deliveryReceiptDO : doList) {
            DeliveryReceiptVO deliveryReceiptVO = new DeliveryReceiptVO();
            BeanUtils.copyProperties(deliveryReceiptDO, deliveryReceiptVO);
            deliveryReceiptVO.setPurchaseLevel(getPurchaseLevel(deliveryReceiptDO.getId()));
            int recordCount = deliveryReceiptLogisticsMapper.countByDate(deliveryReceiptDO.getBillNo(), org.apache.commons.lang3.time.DateFormatUtils.format(new Date(), "yyyyMMdd"));
            deliveryReceiptVO.setRecordFlag(recordCount > 0 ? DeliveryReceiptVO.RECORD_FLAG_YES : DeliveryReceiptVO.RECORD_FLAG_NO);
            voList.add(deliveryReceiptVO);
        }
        pageCommonVO.setPageInfo(new PageInfo(doList));
        pageCommonVO.setPageInfoList(voList);
        return pageCommonVO;
    }

    public List<DeliveryReceiptVO> billNoByNoteNo(String deliveryNoteNo) {
        List<DeliveryReceiptDO> doList = deliveryReceiptMapper.billNoByNoteNo(deliveryNoteNo);
        List<DeliveryReceiptVO> voList = new ArrayList<>();
        for (DeliveryReceiptDO deliveryceiptDO : doList
        ) {
            DeliveryReceiptVO deliveryReceiptVO = new DeliveryReceiptVO();
            BeanUtils.copyProperties(deliveryceiptDO, deliveryReceiptVO);
            voList.add(deliveryReceiptVO);
        }
        return voList;
    }

    @Transactional(rollbackFor = Exception.class)
    public ActionResult add(OperateDeliveryReceiptVO operateDeliveryReceiptVO) throws Exception {
        String billType = operateDeliveryReceiptVO.getDeliveryReceiptVO().getBillType();
        DeliveryReceiptDO deliveryReceiptDO = new DeliveryReceiptDO();
        BeanUtils.copyProperties(operateDeliveryReceiptVO.getDeliveryReceiptVO(), deliveryReceiptDO);
        deliveryReceiptDO.setThreeDayPlan(operateDeliveryReceiptVO.getThreeDayPlan());
        deliveryReceiptDO.setPlanDate(operateDeliveryReceiptVO.getPlanDate());
        deliveryReceiptDO.setCreateDate(new Date());
        deliveryReceiptDO.setUpdateDate(new Date());
        CompanyInfoVO companyInfoVO = companyInfoService.info(deliveryReceiptDO.getOrgId());
        if (!isCanInsert(billType, operateDeliveryReceiptVO.getBillList(), companyInfoVO, operateDeliveryReceiptVO.getSubmitType())) {
            return ActionResultUtil.errorActionResult(ErrorCode.AddressIsUnlikeness);
        }
        String companyNmae = null == companyInfoVO ? "" : companyInfoVO.getCompanyName();
        deliveryReceiptDO.setOrgName(companyNmae);
        ActionResult<String> textResult = fastGenClient.textGuid();
        if (textResult.getCode() != ErrorCode.Success.getCode()) {
            return ActionResultUtil.errorActionResult(ErrorCode.IllegalArument);
        }
        String billId = textResult.getValue();
        deliveryReceiptDO.setId(billId);
        //进出库运单编号不同
        if (!StringUtils.isEmpty(companyInfoVO.getSapCode()) && "4060".equals(companyInfoVO.getSapCode())) {
            deliveryReceiptDO.setBillNo(genDocumentService.genDocumentNo(BillDesc.JCKDeliveryReceiptNo, deliveryReceiptDO.getOrgId()));
        } else {
            deliveryReceiptDO.setBillNo(genDocumentService.genDocumentNo(BillDesc.DeliveryReceiptNo, deliveryReceiptDO.getOrgId()));
        }
        //设置发运交接单的审核状态,需求http://10.90.1.198/zentao/story-view-2916.html
        DataDictionaryDO auditDataDictionaryDO = null;
        String auditDesc = null;
        boolean deliveryReceiptAuditSetting = systemParameterService.getDeliveryReceiptAuditSetting(deliveryReceiptDO.getOrgId());
        if (deliveryReceiptAuditSetting) {
            deliveryReceiptDO.setAuditStatus(DeliveryReceiptEnum.Status.WaitAudit.toString());
            auditDataDictionaryDO = dataDictionaryMapper.itemByCode(DeliveryReceiptEnum.Status.Name.toString(), DeliveryReceiptEnum.Status.WaitAudit.toString());
            auditDesc = "待审核";
        } else {
            deliveryReceiptDO.setAuditStatus(DeliveryReceiptEnum.Status.AuditPass.toString());
            auditDataDictionaryDO = dataDictionaryMapper.itemByCode(DeliveryReceiptEnum.Status.Name.toString(), DeliveryReceiptEnum.Status.AuditPass.toString());
            auditDesc = "审核通过";
            deliveryReceiptDO.setAuditDate(new Date());
            deliveryReceiptDO.setAuditId("00001");
            deliveryReceiptDO.setAuditName("系统自动");
        }
        if (auditDataDictionaryDO != null) {
            auditDesc = auditDataDictionaryDO.getName();
        }
        deliveryReceiptDO.setAuditDesc(auditDesc);
        deliveryReceiptDO.setIsDel(false);
        deliveryReceiptDO.setDeliveryStatus(DeliveryReceiptEnum.DeliveryStatus.UnDelivery.toString());
        DataDictionaryDO deliveryDataDictionaryDO = dataDictionaryMapper.itemByCode(DeliveryReceiptEnum.DeliveryStatus.Name.toString(), DeliveryReceiptEnum.DeliveryStatus.UnDelivery.toString());
        String deliveryStatusDesc = "未发货";
        if (deliveryDataDictionaryDO != null) {
            deliveryStatusDesc = deliveryDataDictionaryDO.getName();
        }
        deliveryReceiptDO.setDeliveryDesc(deliveryStatusDesc);
        deliveryReceiptDO.setCommitType(0);
        ActionResult userAuth = authClient.getUserDetail(deliveryReceiptDO.getCreateId());
        UserCacheDTO userInfo = (UserCacheDTO) userAuth.getValue();
        if (deliveryReceiptDO.getCreateName() == null && userInfo != null) {
            deliveryReceiptDO.setCreateName(userInfo.getName());
            deliveryReceiptDO.setUpdateId(userInfo.getName());
        }
        if (deliveryReceiptDO.getSalesType() == "0") { //暂时先写死，做三包出库的时候根据三包方案修改
            deliveryReceiptDO.setSalesTypeDesc("正常销售");
        } else {
            deliveryReceiptDO.setSalesTypeDesc("三包");
        }
        List<DeliveryReceiptLinkVO> linkList = operateDeliveryReceiptVO.getBillList();

        // 发出仓库
        deliveryReceiptDO.setOutLocation(getOutLocation(linkList.get(0)));

        List<String> deliveryNoteNos = linkList.stream().map(DeliveryReceiptLinkVO::getDeliveryNoteNo).collect(Collectors.toList());
        //服务信息单号
        List<String> billNoList = linkList.stream().map(DeliveryReceiptLinkVO::getSaleBillNo).collect(Collectors.toList());
        if (billType.equals(BillDesc.ThreeOut.getDesc())) {//三包出库单需要服务信息单号
            String purchaseNo = billNoList.get(0);
            List<ThreeGuaranteesPurDO> purDOList = threeGuaranteesPurMapper.findByBillNo(purchaseNo);
            if (!ObjectUtils.isEmpty(purDOList)) {
                deliveryReceiptDO.setServiceNo(purDOList.get(0).getServiceNo());
            }
            //add by wangzhaoyu  三包出库单，指定主机厂不能重复发运
            if (!threeGuaranteesCouldDulp(deliveryReceiptDO.getOrgId(), companyInfoVO.getSapCode()) && !CollectionUtils.isEmpty(deliveryNoteNos)) {
                //查询单号是否已经存在
                List<String> existedDeliveryNoteNos = deliveryReceiptLinkMapper.existedDeliveryReceipt(deliveryNoteNos, deliveryReceiptDO.getOrgId());
                if (!CollectionUtils.isEmpty(existedDeliveryNoteNos)) {
                    String errorBusonessOrder = existedDeliveryNoteNos.get(0);
                    return ActionResultUtil.errorActionResult(ErrorCode.IllegalArument.getCode(), "出库单" + errorBusonessOrder + "不能重复发运");
                }
            }
        }

        List<String> statusList = linkList.stream().map(DeliveryReceiptLinkVO::getStatus).collect(Collectors.toList());

        //出库状态
        setOutStatus(deliveryReceiptDO, statusList);

        if (deliveryReceiptMapper.insert(deliveryReceiptDO) <= 0) {
            return ActionResultUtil.errorActionResult(ErrorCode.Failure);
        }
        List<String> outIds = new ArrayList<>();


        for (DeliveryReceiptLinkVO billVO : linkList) {
            DeliveryReceiptLinkDO deliveryReceiptLinkDO = new DeliveryReceiptLinkDO();
            BeanUtils.copyProperties(billVO, deliveryReceiptLinkDO);
            deliveryReceiptLinkDO.setDeliveryBillId(billId);
            deliveryReceiptLinkDO.setDeliveryBillNo(deliveryReceiptDO.getBillNo());
            if (deliveryReceiptLinkMapper.insert(deliveryReceiptLinkDO) <= 0) {
                return ActionResultUtil.errorActionResult(ErrorCode.Failure);
            }
            outIds.add(deliveryReceiptLinkDO.getDeliveryNoteId());
            //更新三日计划交货状态
            updateThreeDayPlanDlvStatus(billVO.getbId(), 1);
        }
        deliveryReceiptMaterialService.add(outIds, deliveryReceiptDO);

        List<ThreeGuaranteesPurDO> threeGuaranteesPurDOList = new ArrayList<>();
        for (String billNo : billNoList) {
            ThreeGuaranteesPurDO threeGuaranteesPurDO = new ThreeGuaranteesPurDO();
            threeGuaranteesPurDO.setPurchaseNo(billNo);
            threeGuaranteesPurDO.setDeliveryReceiptTime(new Date());
            threeGuaranteesPurDOList.add(threeGuaranteesPurDO);
        }

        //更新三包申请的发运时间
        if (deliveryReceiptDO.getBillType().equals(billType.equals(BillDesc.ThreeOut.getDesc())) && !ObjectUtils.isEmpty(threeGuaranteesPurDOList)) {
            threeGuaranteesPurMapper.updateDeliveryReceiptByBillNo(threeGuaranteesPurDOList);
        }

        return ActionResultUtil.errorActionResult(ErrorCode.Success);
    }

    /**
     * 根据当前单据的出库状态判断发运交接单的出库状态
     * 当前单据全为未出库，则发运交接单为未出库
     * 当前单据全为已出库，则发运交接单为已出库
     * 否则为部分出库
     *
     * @param deliveryReceiptDO
     * @param statusList
     */
    private void setOutStatus(DeliveryReceiptDO deliveryReceiptDO, List<String> statusList) {
        if (statusList.stream().allMatch(o -> !StringUtil.isNotEmpty(o) || "0".equals(o))) {
            deliveryReceiptDO.setOutStatus(0);
        } else if (statusList.stream().allMatch(o -> StringUtil.isNotEmpty(o) && "2".equals(o))) {
            deliveryReceiptDO.setOutStatus(2);
        } else {
            deliveryReceiptDO.setOutStatus(1);
        }
    }

    /**
     * 这里的代码是之前的，虽然很丑，但是暂时无错，就不改了。
     * 需要加上一个规则：如果是施维英，只校验收货人电话，不校验地址和客户名。此处应该用Set，不需要后面的多余的equals比较
     * wangyong 20200325
     *
     * @param type
     * @param linkList
     * @return
     */
    private boolean isCanInsert(String type, List<DeliveryReceiptLinkVO> linkList, CompanyInfoVO companyInfoVO, String submitType) {
        List<String> addressList = new ArrayList<>();
        Set<String> receiverSet = new HashSet<>();
        for (DeliveryReceiptLinkVO billVO : linkList) {
            switch (type) {
                case "XGFT":
                    DeliveryNoteDO deliveryNoteDO = deliveryNoteMapper.item(billVO.getDeliveryNoteId());
                    if (deliveryNoteDO == null) {
                        return false;
                    }
                    //如果是1代表进出口运单提交，只判断国家是否相同
                    if (StringUtils.equals("1", submitType)) {
                        if (deliveryNoteDO.getCountry() != null) {
                            addressList.add(deliveryNoteDO.getCountry());
                        }
                    } else {
                        if (deliveryNoteDO.getAddress() != null) {
                            addressList.add(deliveryNoteDO.getAddress());
                        }
                    }

                    receiverSet.add(deliveryNoteDO.getReceiverPhone());
                    break;
                case "XGSC":
                    ThreeGuaranteesOutDO threeGuaranteesOutDO = threeGuaranteesOutMapper.item(billVO.getDeliveryNoteId());
                    if (threeGuaranteesOutDO == null) {
                        return false;
                    }
                    if (threeGuaranteesOutDO.getAddress() != null) {
                        addressList.add(threeGuaranteesOutDO.getAddress());
                    }
                    receiverSet.add(threeGuaranteesOutDO.getReceiverPhone());
                    break;
                case "XGQD":
                    RegionAllotDO regionAllotDO = regionAllotMapper.selectByPrimaryKey(billVO.getDeliveryNoteId());
                    if (regionAllotDO == null) {
                        return false;
                    }
                    if (regionAllotDO.getReceiveAddress() != null) {
                        addressList.add(regionAllotDO.getReceiveAddress());
                    }
                    receiverSet.add(regionAllotDO.getReceiveTel());
                    break;
                case "XGFC":
                    AbnormalOutDO abnormalOutDO = abnormalOutMapper.item(billVO.getDeliveryNoteId());
                    if (abnormalOutDO == null) {
                        return false;
                    }
                    if (abnormalOutDO.getAddress() != null) {
                        addressList.add(abnormalOutDO.getAddress());
                    }
                    receiverSet.add(abnormalOutDO.getReceiverPhone());
                    break;
                case "XSCK":
                    SalesOutBillDO salesOutBillDO = salesOutBillMapper.selectByPrimaryKey(billVO.getDeliveryNoteId());
                    if (salesOutBillDO == null) {
                        return false;
                    }
                    if (StringUtils.isNotBlank(salesOutBillDO.getReceiptAddress())) {
                        addressList.add(salesOutBillDO.getReceiptAddress());
                    }
                    receiverSet.add(salesOutBillDO.getContactPhone());
                    break;
                default:
                    return true;
            }
        }
        if (CompanyUtil.isSWY(companyInfoVO.getSapCode())) {
            if (receiverSet.size() > 1) {
                return false;
            }
        } else {
            if (addressList.size() > 1) {
                String address = addressList.get(0);
                for (String nextAddress : addressList) {
                    if (!address.equals(nextAddress)) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    private void updateThreeDayPlanDlvStatus(String bid, Integer status) {
        if (StringUtils.isBlank(bid)) {
            return;
        }
        //更新三日计划状态
        ThreeDayPlanDetailDO threeDayPlanDetailDO = threeDayPlanDetailDOMapper.selectByPrimaryKey(bid);
        if (null != threeDayPlanDetailDO) {
            threeDayPlanDetailDOMapper.updateById(bid, status);
            String mainId = threeDayPlanDetailDO.getMainId();
            int zeroCount = threeDayPlanDetailDOMapper.getZeroCountByMainId(mainId);
            int count = threeDayPlanDetailDOMapper.getCountByMainId(mainId);
            if (zeroCount < count) {
                status = 1;
            } else if (zeroCount == count) {
                status = 0;
            }
            if (zeroCount == 0) {
                status = 2;
            }
            threeDayPlanDOMapper.updateById(mainId, status);
        }
    }

    /**
     * 获取发运交接单的发出仓库
     *
     * @param receiptLinkVO
     * @return
     */
    private String getOutLocation(DeliveryReceiptLinkVO receiptLinkVO) {
        String warehouse = StringUtils.EMPTY;

        // 发货通知单
        if (BillDesc.DeliveryNo.getDesc().equals(receiptLinkVO.getBillType())) {
//            outLocation
            DeliveryNoteDO deliveryNoteDO = deliveryNoteMapper.item(receiptLinkVO.getDeliveryNoteId());
            warehouse = deliveryNoteDO.getOutLocation();
            //三包出库单
        } else if (BillDesc.ThreeOut.getDesc().equals(receiptLinkVO.getBillType())) {

            ThreeGuaranteesOutDO outDO = threeGuaranteesOutMapper.item(receiptLinkVO.getDeliveryNoteId());
            warehouse = outDO.getOutLocation();
            //区域调拨单
        } else if (BillDesc.RegionAllot.getDesc().equals(receiptLinkVO.getBillType())) {

            RegionAllotDO regionAllotDO = regionAllotMapper.selectByPrimaryKey(receiptLinkVO.getDeliveryNoteId());
            warehouse = regionAllotDO.getOutLocation();
            //其它出库单
        } else if (BillDesc.AbnormalOutNo.getDesc().equals(receiptLinkVO.getBillType())) {
            AbnormalOutDO abnormalOutDO = abnormalOutMapper.item(receiptLinkVO.getDeliveryNoteId());
            warehouse = abnormalOutDO.getOutLocation();
        } else {
            //nothing
        }
        return warehouse;
    }

    @Transactional(rollbackFor = Exception.class)
    public ErrorCode update(OperateDeliveryReceiptVO operateDeliveryReceiptVO) throws Exception {
        if (operateDeliveryReceiptVO.getDeliveryReceiptVO().getId() == null || operateDeliveryReceiptVO.getDeliveryReceiptVO().getId() == "") {
            return ErrorCode.DeliveryReceiptBillIdNotExists;
        }
        DeliveryReceiptDO deliveryReceiptDO = deliveryReceiptMapper.item(operateDeliveryReceiptVO.getDeliveryReceiptVO().getId());
        if (deliveryReceiptDO == null) {
            return ErrorCode.DeliveryReceiptInfoNotExists;
        }
        int newInsertBusinessOrder = 0;//记录本次更新操作新增的单据数
        List<DeliveryReceiptLinkDO> billDOList = deliveryReceiptLinkMapper.list(deliveryReceiptDO.getId());
        for (DeliveryReceiptLinkVO billVO : operateDeliveryReceiptVO.getBillList()) {
            DeliveryReceiptLinkDO billDO = new DeliveryReceiptLinkDO();
            BeanUtils.copyProperties(billVO, billDO);
            if (billDOList.contains(billDO)) {
                billDOList.remove(billDO);//剩余的是需要删除的
                continue;
            }
            DeliveryReceiptLinkDO deliveryReceiptLinkDO = new DeliveryReceiptLinkDO();
            BeanUtils.copyProperties(billVO, deliveryReceiptLinkDO);
            deliveryReceiptLinkDO.setDeliveryBillId(operateDeliveryReceiptVO.getDeliveryReceiptVO().getId());
            deliveryReceiptLinkDO.setDeliveryBillNo(operateDeliveryReceiptVO.getDeliveryReceiptVO().getBillNo());
            if (deliveryReceiptLinkMapper.insert(deliveryReceiptLinkDO) <= 0) {
                return ErrorCode.Failure;
            }

            //更新三日计划交货状态
            updateThreeDayPlanDlvStatus(billVO.getbId(), 1);
            newInsertBusinessOrder++;
        }
        for (DeliveryReceiptLinkDO billDO : billDOList) {
            if (deliveryReceiptMapper.boxDetailCount(billDO.getDeliveryBillId(), billDO.getDeliveryNoteId()) > 0) {
                throw new Exception("该发货通知单已装箱，不可删除");
            }
            deliveryReceiptLinkMapper.deleteItem(billDO.getDeliveryBillId(), billDO.getDeliveryNoteId());
            // 清空出库记录中关联该发运交接单号的记录中发运交接单号
            resetDeliveryRecordReceiptNo(billDO);

            //更新三日计划交货状态
            updateThreeDayPlanDlvStatus(billDO.getbId(), 0);
        }
        //如果本次编辑存在业务单据的删除或者新增，则需要进行以下操作
        if (newInsertBusinessOrder > 0 || billDOList.size() > 0) {
            // 删除掉更新前的出库事务单和单据零件表,然后把新的信息拼接保存起来
            editDeliveryReceiptDelHandle(deliveryReceiptDO);
            // 更新操作后，统计发运交接单单据的出库状态并更新
            List<DeliveryReceiptLinkDO> deliveryReceiptLinks = deliveryReceiptLinkMapper.findDeliveryNoteIds(deliveryReceiptDO.getId());
            List<String> outIds = deliveryReceiptLinks.stream().map(DeliveryReceiptLinkDO::getDeliveryNoteId).collect(Collectors.toList());
            deliveryReceiptMaterialService.add(outIds, deliveryReceiptDO);
            // 统计新的出库状态并赋值给实体，进行更新
            List<String> statusList = deliveryReceiptLinks.stream().map(DeliveryReceiptLinkDO::getStatus).collect(Collectors.toList());
            setOutStatus(deliveryReceiptDO, statusList);
        }

        ActionResult userAuth = authClient.getUserDetail(deliveryReceiptDO.getUpdateId());
        //拼接需要更新的信息
        assembleUpdateDO(deliveryReceiptDO, operateDeliveryReceiptVO, userAuth);

        //审核状态重置
        resetAuditStatus(deliveryReceiptDO.getOrgId(), deliveryReceiptDO);
        if (deliveryReceiptMapper.editupdate(deliveryReceiptDO) <= 0) {
            throw new Exception("更新单据信息异常");
        }
        return ErrorCode.Success;
    }

    private void resetDeliveryRecordReceiptNo(DeliveryReceiptLinkDO billDO) {
        if (billDO == null) {
            return;
        }
        String receiptNo = billDO.getDeliveryBillNo();
        String businessOrder = billDO.getDeliveryNoteNo();
        warehouseDeliveryRecordMapper.resetReceiptNo(receiptNo, businessOrder);
    }

    /**
     * @Des 发运交接单更新操作时删除
     * @Date 2021/4/20 14:44
     * @Author wangzhaoyu
     * @Param [deliveryReceiptDO]
     * @Return void
     */
    private void editDeliveryReceiptDelHandle(DeliveryReceiptDO deliveryReceiptDO) throws Exception {
        if (deliveryReceiptDO == null) {
            return;
        }
        String receiptBillId = deliveryReceiptDO.getId();
        String orgId = deliveryReceiptDO.getOrgId();
        if (StringUtils.isEmpty(receiptBillId)) {
            return;
        }
        // 删除发运交接单零件信息
        int receiptMaterialDelResult = deliveryReceiptMaterialMapper.deleteByDeliveryReceiptId(receiptBillId);
        if (receiptMaterialDelResult <= 0) {
            throw new Exception("更新发运交接单零件失败");
        }
        String billNo = deliveryReceiptDO.getBillNo();
        // 删除发运交接单出库事务表(主表和子表记录都删除)
        int deliveryDetailDelResult = warehouseDeliveryDetailMapper.deleteByBusinessOrderAndOrgId(billNo, orgId);
        if (deliveryDetailDelResult <= 0) {
            throw new Exception("更新出库单失败");
        }
        int deliveryDelResult = warehouseDeliveryMapper.hardDeleteByBusinessOrder(billNo, orgId);
        if (deliveryDelResult <= 0) {
            throw new Exception("更新出库单失败");
        }
    }

    /**
     * @Des 拼接需要更新的实体信息
     * @Date 2021/4/20 13:43
     * @Author wangzhaoyu
     * @Param [deliveryReceiptDO, operateDeliveryReceiptVO]
     * @Return void
     */
    private void assembleUpdateDO(DeliveryReceiptDO deliveryReceiptDO, OperateDeliveryReceiptVO operateDeliveryReceiptVO, ActionResult userAuth) {
        //refectorying by wanngzhaoyu
        //add by  huhuawei 2018-9-19
        deliveryReceiptDO.setBasicId(operateDeliveryReceiptVO.getDeliveryReceiptVO().getBasicId());
        deliveryReceiptDO.setCommitmentTime(operateDeliveryReceiptVO.getDeliveryReceiptVO().getCommitmentTime());

        deliveryReceiptDO.setDeliveryDate(operateDeliveryReceiptVO.getDeliveryReceiptVO().getDeliveryDate());
        deliveryReceiptDO.setCarrierAmount(operateDeliveryReceiptVO.getDeliveryReceiptVO().getCarrierAmount());
        deliveryReceiptDO.setCarrierOrgId(operateDeliveryReceiptVO.getDeliveryReceiptVO().getCarrierOrgId());
        deliveryReceiptDO.setCarrierOrgName(operateDeliveryReceiptVO.getDeliveryReceiptVO().getCarrierOrgName());
        deliveryReceiptDO.setCarrierUserName(operateDeliveryReceiptVO.getDeliveryReceiptVO().getCarrierUserName());
        deliveryReceiptDO.setCarrierCar(operateDeliveryReceiptVO.getDeliveryReceiptVO().getCarrierCar());
        deliveryReceiptDO.setFreightNo(operateDeliveryReceiptVO.getDeliveryReceiptVO().getFreightNo());
        deliveryReceiptDO.setReceiverSite(operateDeliveryReceiptVO.getDeliveryReceiptVO().getReceiverSite());
        deliveryReceiptDO.setReceiverName(operateDeliveryReceiptVO.getDeliveryReceiptVO().getReceiverName());
        deliveryReceiptDO.setReceiverTel(operateDeliveryReceiptVO.getDeliveryReceiptVO().getReceiverTel());
        deliveryReceiptDO.setReceiverFax(operateDeliveryReceiptVO.getDeliveryReceiptVO().getReceiverFax());
        deliveryReceiptDO.setReceiverAddress(operateDeliveryReceiptVO.getDeliveryReceiptVO().getReceiverAddress());
        deliveryReceiptDO.setShippingMethod(operateDeliveryReceiptVO.getDeliveryReceiptVO().getShippingMethod());
        deliveryReceiptDO.setShippingMethodId(operateDeliveryReceiptVO.getDeliveryReceiptVO().getShippingMethodId());
        deliveryReceiptDO.setShippingSecondMethod(operateDeliveryReceiptVO.getDeliveryReceiptVO().getShippingSecondMethod());
        deliveryReceiptDO.setShippingSecondMethodId(operateDeliveryReceiptVO.getDeliveryReceiptVO().getShippingSecondMethodId());
        deliveryReceiptDO.setExpressCode(operateDeliveryReceiptVO.getDeliveryReceiptVO().getExpressCode());
        deliveryReceiptDO.setDealerOrgId(operateDeliveryReceiptVO.getDeliveryReceiptVO().getDealerOrgId());
        deliveryReceiptDO.setDealerOrgName(operateDeliveryReceiptVO.getDeliveryReceiptVO().getDealerOrgName());
        deliveryReceiptDO.setTotalWeight(operateDeliveryReceiptVO.getDeliveryReceiptVO().getTotalWeight());
        deliveryReceiptDO.setFreight(operateDeliveryReceiptVO.getDeliveryReceiptVO().getFreight());
        deliveryReceiptDO.setRemark(operateDeliveryReceiptVO.getDeliveryReceiptVO().getRemark());
        deliveryReceiptDO.setDeliveryTime(operateDeliveryReceiptVO.getDeliveryReceiptVO().getDeliveryTime());
        deliveryReceiptDO.setCountry(operateDeliveryReceiptVO.getDeliveryReceiptVO().getCountry());
        deliveryReceiptDO.setPurchaseContractNo(operateDeliveryReceiptVO.getDeliveryReceiptVO().getPurchaseContractNo());
        deliveryReceiptDO.setCheckerName(operateDeliveryReceiptVO.getDeliveryReceiptVO().getCheckerName());
        deliveryReceiptDO.setAccessoriesFee(operateDeliveryReceiptVO.getDeliveryReceiptVO().getAccessoriesFee());//辅料费用
        if (userAuth != null) {
            UserCacheDTO userInfo = (UserCacheDTO) userAuth.getValue();
            if (userInfo != null) {
                deliveryReceiptDO.setUpdateId(userInfo.getName());
            }
        }
        return;
    }

    /**
     * @Des 编辑发运交接单时重置审核信息
     * @Date 2021/4/13 17:03
     * @Author wangzhaoyu
     * @Param [orgId, deliveryReceiptDO]
     * @Return void
     */
    private void resetAuditStatus(String orgId, DeliveryReceiptDO oldDeliveryReceiptDO) {
        //如果发运交接单老的审核状态是审核通过的则不重置审核信息
        String auditStatus = oldDeliveryReceiptDO.getAuditStatus();
        if (StringUtils.isNotEmpty(auditStatus) && auditStatus.equals(DeliveryReceiptAuditStatusEnum.AUDIT_PASS.getAuditStatus().toString())) {
            return;
        }
        if (StringUtils.isNotEmpty(auditStatus) && auditStatus.equals(DeliveryReceiptAuditStatusEnum.AUDIT_REJECT.getAuditStatus().toString())) {
            //查看公司是否需要有审核流程
            boolean deliveryReceiptAuditSetting = systemParameterService.getDeliveryReceiptAuditSetting(orgId);
            if (deliveryReceiptAuditSetting) {
                oldDeliveryReceiptDO.setAuditName(null);
                oldDeliveryReceiptDO.setAuditId(null);
                oldDeliveryReceiptDO.setAuditDate(null);
                String newAuditStatus = DeliveryReceiptAuditStatusEnum.AUDIT_WAIT.getAuditStatus();
                DataDictionaryDO auditDataDictionaryDO = dataDictionaryMapper.itemByCode(DeliveryReceiptEnum.Status.Name.toString(), newAuditStatus);
                String auditDesc = auditDataDictionaryDO == null ? "" : auditDataDictionaryDO.getName();
                oldDeliveryReceiptDO.setAuditDesc(auditDesc);
                oldDeliveryReceiptDO.setAuditStatus(newAuditStatus);
                oldDeliveryReceiptDO.setAuditMessage(null);
            }
        }
    }

    public ErrorCode updateLogsic(DeliveryReceiptVO deliveryReceiptVO) {
        DeliveryReceiptDO deliveryReceiptDO = deliveryReceiptMapper.itemByNo(deliveryReceiptVO.getBillNo());
        if (deliveryReceiptDO == null) {
            return ErrorCode.IllegalArument;
        }
        deliveryReceiptDO.setFreightNo(deliveryReceiptVO.getFreightNo());
        return deliveryReceiptMapper.update(deliveryReceiptDO) > 0 ? ErrorCode.Success : ErrorCode.Failure;
    }

    public OperateDeliveryReceiptVO getInfo(String billId) {
        DeliveryReceiptDO deliveryReceiptDO = deliveryReceiptMapper.item(billId);
        if (deliveryReceiptDO == null) {
            return null;
        }
        List<DeliveryReceiptLinkDO> billDOList = deliveryReceiptLinkMapper.list(billId);
        OperateDeliveryReceiptVO operateDeliveryReceiptVO = new OperateDeliveryReceiptVO();
        DeliveryReceiptVO deliveryReceiptVO = new DeliveryReceiptVO();
        List<DeliveryReceiptLinkVO> billVOlist = new ArrayList<>();
        BeanUtils.copyProperties(deliveryReceiptDO, deliveryReceiptVO);
        String expressCode = deliveryReceiptVO.getExpressCode();
        if (StringUtils.isNotBlank(expressCode)) {
            deliveryReceiptVO.setExpressName(expressCodeInfoMapper.getNameByCode(expressCode));
        }
        operateDeliveryReceiptVO.setPlanDate(deliveryReceiptDO.getPlanDate());
        operateDeliveryReceiptVO.setThreeDayPlan(deliveryReceiptDO.getThreeDayPlan());
        if (StringUtils.equals(deliveryReceiptDO.getBillType(), BillDesc.DeliveryNo.getDesc())) {
            deliveryReceiptVO.setPurchaseLevel(getPurchaseLevel(deliveryReceiptVO.getId()));
        }
        deliveryReceiptVO.setBillTypeDesc(getBillDesc(deliveryReceiptVO.getBillType()));
        for (DeliveryReceiptLinkDO linkDO : billDOList
        ) {
            DeliveryReceiptLinkVO deliveryReceiptLinkVO = new DeliveryReceiptLinkVO();
            BeanUtils.copyProperties(linkDO, deliveryReceiptLinkVO);
            // 如果来源单据是三包出库
            if (BILL_TYPE_THREE_OUT.equals(linkDO.getBillType())) {
                deliveryReceiptLinkVO.setThreeGuaServiceVO(fillThreeGuaServiceInfo(linkDO.getDeliveryNoteId()));
            }
            billVOlist.add(deliveryReceiptLinkVO);
        }
        BoxupMainVO mainVO = new BoxupMainVO();
        mainVO.setDeliveryReceiptId(deliveryReceiptDO.getId());
        mainVO.setDeliveryReceiptNo(deliveryReceiptDO.getBillNo());
        List<BoxupMainDO> mainDOList = boxupMainMapper.list(mainVO);

        //查询包装规格成本费用
        Map<String, PackageSpecDO> packageSpecDOMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(mainDOList)) {
            List<String> packageSpecIds = mainDOList.stream().filter(boxupMainDO -> boxupMainDO.getPackageSpecId() != null)
                    .map(BoxupMainDO::getPackageSpecId).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(packageSpecIds)) {
                PackageSpecDO packageSpecDO = new PackageSpecDO();
                packageSpecDO.setIdList(packageSpecIds);
                List<PackageSpecDO> specDOList = packageSpecDOMapper.list(packageSpecDO);
                if (CollectionUtils.isNotEmpty(specDOList)) {
                    packageSpecDOMap = specDOList.stream().collect(Collectors.toMap(PackageSpecDO::getId, Function.identity(), (k1, k2) -> k2));
                }
            }


        }
        List<BoxupMainVO> mainVOList = new ArrayList<>();
        for (BoxupMainDO mainDOs : mainDOList) {
            BoxupMainVO mainVOs = new BoxupMainVO();
            BeanUtils.copyProperties(mainDOs, mainVOs);
            BigDecimal cost = BigDecimal.ZERO;
            String packageSpecId = mainDOs.getPackageSpecId();
            if (StringUtils.isNotEmpty(packageSpecId) && packageSpecDOMap.containsKey(packageSpecId)) {
                cost = packageSpecDOMap.get(packageSpecId).getCost();
            }
            mainVOs.setCost(cost);
            mainVOList.add(mainVOs);
        }
        List<BoxupDetailVO> materialsList = boxupMainService.beenPackList(deliveryReceiptVO.getBillNo());

        List<DeliveryReceiptLogisticsVO> listVO = new ArrayList<>();
        List<DeliveryReceiptLogisticsDO> listDO = deliveryReceiptLogisticsMapper.list(deliveryReceiptVO.getBillNo());
        for (DeliveryReceiptLogisticsDO entity : listDO) {
            DeliveryReceiptLogisticsVO model = new DeliveryReceiptLogisticsVO();
            BeanUtils.copyProperties(entity, model);
            listVO.add(model);
        }
        operateDeliveryReceiptVO.setLogisticsVOList(listVO);
        operateDeliveryReceiptVO.setMaterialsList(materialsList);
        operateDeliveryReceiptVO.setMainVOList(mainVOList);
        operateDeliveryReceiptVO.setDeliveryReceiptVO(deliveryReceiptVO);
        operateDeliveryReceiptVO.setBillList(billVOlist);

        List<WarehouseDeliveryDetailVO> materialsMergeList = new ArrayList<>();
        List<WarehouseDeliveryDetailDO> deliveryDetailDOList = this.listMore(deliveryReceiptDO.getBillType(), deliveryReceiptDO.getBillNo());
        if (!ListUtil.isNullOrEmpty(deliveryDetailDOList)) {
            for (WarehouseDeliveryDetailDO detailDO : deliveryDetailDOList) {
                WarehouseDeliveryDetailVO deliveryDetailVO = new WarehouseDeliveryDetailVO();
                BeanUtils.copyProperties(detailDO, deliveryDetailVO);
                String locationCode = deliveryDetailVO.getLocationCode();
                if (StringUtils.isNotBlank(locationCode)) {
                    String[] locationCodeSplit = locationCode.split(",");
                    List<String> locationDescList = new ArrayList<>();
                    for (String aLocationCodeSplit : locationCodeSplit) {
                        String locationDesc = warehouseAreaLocationDOMapper.getLocationDesc(aLocationCodeSplit);
                        locationDescList.add(locationDesc);
                    }
                    deliveryDetailVO.setLocationDesc(locationDescList.stream().collect(Collectors.joining(",")));
                }
                materialsMergeList.add(deliveryDetailVO);
            }
        }
        operateDeliveryReceiptVO.setMaterialsMergeList(materialsMergeList);
        return operateDeliveryReceiptVO;
    }

    private ThreeGuaServiceVO fillThreeGuaServiceInfo(String threeGuaranteesOutId) {
        if (StringUtils.isEmpty(threeGuaranteesOutId)) {
            return new ThreeGuaServiceVO();
        }
        ThreeGuaranteesOutDO threeGuaranteesOutDO = threeGuaranteesOutMapper.item(threeGuaranteesOutId);
        if (null == threeGuaranteesOutDO) {
            return new ThreeGuaServiceVO();
        }
        ThreeGuaranteesPurDO threeGuaranteesPurDO = threeGuaranteesPurMapper.itemByNo(threeGuaranteesOutDO.getPurchaseNo(), threeGuaranteesOutDO.getOrgId());
        if (null == threeGuaranteesPurDO) {
            return new ThreeGuaServiceVO();
        }
        ThreeGuaServiceVO serviceVO = new ThreeGuaServiceVO();
        serviceVO.setCrmOrder(threeGuaranteesPurDO.getCrmOrder());
        serviceVO.setMachineNumber(threeGuaranteesPurDO.getMachineNumber());
        serviceVO.setProdType(threeGuaranteesPurDO.getProdType());
        serviceVO.setServiceName(threeGuaranteesPurDO.getServiceName());
        serviceVO.setServiceSite(threeGuaranteesPurDO.getServiceSite());
        return serviceVO;
    }

    private String getPurchaseLevel(String deliveryReceiptId) {
        List<DeliveryReceiptLinkDO> linkDOS = deliveryReceiptLinkMapper.list(deliveryReceiptId);
        if (CollectionUtils.isNotEmpty(linkDOS)) {
            List<String> list = new ArrayList<>();
            for (DeliveryReceiptLinkDO linkDO : linkDOS) {
                DeliveryNoteDO deliveryNoteDO = deliveryNoteMapper.item(linkDO.getDeliveryNoteId());
                if (null != deliveryNoteDO) {
                    if (StringUtils.equals("紧急", deliveryNoteDO.getPurchaseLevelName())) {
                        return "紧急";
                    }
                    list.add(deliveryNoteDO.getPurchaseLevelName());
                }
            }
            return CollectionUtils.isEmpty(list) ? null : list.get(0);
        }
        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    public ErrorCode shipConfirm(String deliveryReceiptNo, String orgId, String userId) throws Exception {
        CompanyInfoDO companyInfo = companyInfoMapper.item(orgId);
        if (deliveryReceiptNo.startsWith(BillDesc.Boxup.getDesc())) {//装箱单号--按箱发运
            if (CompanyUtil.JCK_SAP_CODE.equals(companyInfo.getSapCode())) {//进出口专用

                BoxupMainVO mainVO = new BoxupMainVO();
                mainVO.setBoxupNo(deliveryReceiptNo);
                mainVO.setOrgId(orgId);
                //查询箱号关联全部装箱单---运单
                List<BoxupMainDO> mainDOList = boxupMainMapper.list(mainVO);
                if (CollectionUtils.isEmpty(mainDOList)) {
                    return ErrorCode.BoxupMainNotExist;
                }

                for (BoxupMainDO boxupMainDO : mainDOList) {

                    DeliveryReceiptDO deliveryReceiptDO = deliveryReceiptMapper.itemByNo(boxupMainDO.getDeliveryReceiptNo());
                    String receiptNo = boxupMainDO.getDeliveryReceiptNo();
                    if (deliveryReceiptDO.getOutStatus() != 2) {//已出库
                        throw new Exception("该装箱单对应进出口运单【" + receiptNo + "】未全部出库");
                    }
                    if (boxupMainDO.getDeliveryStatus() == 1) {
                        return ErrorCode.BoxupMainDeliveryDone;
                    }

                    boxupMainDO.setDeliveryStatus(1);//已发货
                    boxupMainMapper.update(boxupMainDO);

                    // 校验数量修改发货数量---发运单状态
                    if (StringUtils.equals(deliveryReceiptDO.getBillType(), "XGFT")) {
                        List<BoxupDetailTotalDO> qtys = boxupDetailMapper.totalQty(boxupMainDO.getBoxupId());
                        for (BoxupDetailTotalDO detail : qtys) {
                            DeliveryNoteDetailDO deliveryNoteDetailDO = new DeliveryNoteDetailDO();
                            deliveryNoteDetailDO.setSendNumber(detail.getQty());
                            deliveryNoteDetailDO.setMaterialsNo(detail.getMaterialsNo());
                            deliveryNoteDetailDO.setDeliveryNoteNo(detail.getDeliveryNoteId());
                            deliveryNoteDetailMapper.updateSendNumber(deliveryNoteDetailDO);
                            DeliveryNoteDO deliveryNoteDO = new DeliveryNoteDO();
                            deliveryNoteDO.setId(detail.getDeliveryNoteId());
                            deliveryNoteDO.setLogState("1");
                            deliveryNoteDO.setLogStateDescribe("已发货");
                            deliveryNoteMapper.update(deliveryNoteDO);
                        }
                    }

                    //判断是否可继续装箱发货--部分装箱
                    List<BoxupDetailVO> boxupDetailVOS = boxupMainService.notPackList(receiptNo);
                    if (CollectionUtils.isEmpty(boxupDetailVOS)) {
                        deliveryReceiptDO.setCommitType(1);

                        //判断装箱完的是否全部发货
                        BoxupMainVO boxupMainVO = new BoxupMainVO();
                        boxupMainVO.setOrgId(orgId);
                        boxupMainVO.setDeliveryReceiptId(boxupMainDO.getDeliveryReceiptId());
                        List<BoxupMainDO> boxupMainDOS = boxupMainMapper.list(boxupMainVO);
                        if (CollectionUtils.isNotEmpty(boxupMainDOS)) {
                            boolean statusFlag = boxupMainDOS.stream().allMatch(mainDO -> mainDO.getDeliveryStatus() == 1);
                            if (statusFlag) {
                                deliveryReceiptDO.setDeliveryStatus(DeliveryReceiptEnum.DeliveryStatus.Delivered.toString());
                            } else {
                                deliveryReceiptDO.setDeliveryStatus(DeliveryReceiptEnum.DeliveryStatus.PartDelivered.toString());//部分发货
                            }
                        }
                    } else {
                        deliveryReceiptDO.setDeliveryStatus(DeliveryReceiptEnum.DeliveryStatus.PartDelivered.toString());//部分发货
                    }

                    deliveryReceiptDO.setCommitId(userId);
                    deliveryReceiptDO.setCommitTime(new Date());
                    deliveryReceiptDO.setOutStatus(OUT_STATUS_FINISH);
                    DataDictionaryDO deliveryDataDictionaryDO = dataDictionaryMapper.itemByCode(DeliveryReceiptEnum.DeliveryStatus.Name.toString(),
                            deliveryReceiptDO.getDeliveryStatus());
                    String deliveryStatusDesc = "已发货";
                    if (deliveryDataDictionaryDO != null) {
                        deliveryStatusDesc = deliveryDataDictionaryDO.getName();
                    }
                    deliveryReceiptDO.setDeliveryDesc(deliveryStatusDesc);
                    deliveryReceiptMapper.update(deliveryReceiptDO);
                }

            } else {//非进出口给提示
                DeliveryReceiptDO deliveryReceiptDO = deliveryReceiptMapper.itemByNo(deliveryReceiptNo);
                if (deliveryReceiptDO == null) {
                    return ErrorCode.DeliveryReceiptInfoNotExists;
                }
            }
        } else {//运单号--按运单发运
            DeliveryReceiptDO deliveryReceiptDO = deliveryReceiptMapper.itemByNo(deliveryReceiptNo);
            if (deliveryReceiptDO == null) {
                return ErrorCode.DeliveryReceiptInfoNotExists;
            }

            //未发货或者部分发货
            if (!deliveryReceiptDO.getDeliveryStatus().equals(DeliveryReceiptEnum.DeliveryStatus.UnDelivery.toString())
                    && !deliveryReceiptDO.getDeliveryStatus().equals(DeliveryReceiptEnum.DeliveryStatus.PartDelivered.toString())) {
                return ErrorCode.DeliveryReceiptCommited;
            }
            BoxupMainVO boxupMainVO = new BoxupMainVO();
            boxupMainVO.setOrgId(orgId);
            boxupMainVO.setDeliveryReceiptId(deliveryReceiptDO.getId());
            List<BoxupMainDO> boxupMainDOS = boxupMainMapper.list(boxupMainVO);

            //if (!companyUtil.isSC(orgId) && !companyUtil.isTJ(orgId)) {
            if (!canShipConfirm(boxupMainDOS, orgId, deliveryReceiptDO.getOutStatus())) {
                return ErrorCode.DeliveryReceiptNotExistBoxUp;
            }
            //}

            /**
             * 进出口 全部已出库允许发货
             */
            if (CompanyUtil.JCK_SAP_CODE.equals(companyInfo.getSapCode())) {
                if (deliveryReceiptDO.getOutStatus() != 2) {
                    throw new Exception("该进出口运单【" + deliveryReceiptNo + "】未全部出库");
                }
            }

            if (CompanyUtil.isWJ(orgId) || CompanyUtil.isKJ(companyInfo.getSapCode())) {
                //点确认发货时加提示，判断已出库的零件是否全部装箱
                Integer num1 = boxupDetailMapper.boxAlreadyNum(deliveryReceiptDO.getId());
                Integer num2 = boxupDetailMapper.deliveryAlreadyNum(deliveryReceiptDO.getId());
                if (!num1.equals(num2)) {
                    return ErrorCode.DeliveryReceiptNotAllBoxUp;
                }
            }

            if (StringUtils.equals(deliveryReceiptDO.getBillType(), "XGFT")) {
                for (BoxupMainDO box : boxupMainDOS
                ) {
                    List<BoxupDetailTotalDO> qtys = boxupDetailMapper.totalQty(box.getBoxupId());
                    for (BoxupDetailTotalDO detail : qtys
                    ) {
                        DeliveryNoteDetailDO deliveryNoteDetailDO = new DeliveryNoteDetailDO();
                        deliveryNoteDetailDO.setSendNumber(detail.getQty());
                        deliveryNoteDetailDO.setMaterialsNo(detail.getMaterialsNo());
                        deliveryNoteDetailDO.setDeliveryNoteNo(detail.getDeliveryNoteId());
                        deliveryNoteDetailMapper.updateSendNumber(deliveryNoteDetailDO);
                        DeliveryNoteDO deliveryNoteDO = new DeliveryNoteDO();
                        deliveryNoteDO.setId(detail.getDeliveryNoteId());
                        deliveryNoteDO.setLogState("1");
                        deliveryNoteDO.setLogStateDescribe("已发货");
                        deliveryNoteMapper.update(deliveryNoteDO);
                    }
                }
            }
            deliveryReceiptDO.setCommitType(1);
            deliveryReceiptDO.setCommitId(userId);
            deliveryReceiptDO.setCommitTime(new Date());
            deliveryReceiptDO.setDeliveryStatus(DeliveryReceiptEnum.DeliveryStatus.Delivered.toString());
            deliveryReceiptDO.setOutStatus(OUT_STATUS_FINISH);

            //处理部分装箱场景
            if (CompanyUtil.JCK_SAP_CODE.equals(companyInfo.getSapCode())) {//进出口专用
                //判断是否可继续装箱发货--部分装箱
                List<BoxupDetailVO> boxupDetailVOS = boxupMainService.notPackList(deliveryReceiptNo);
                if (CollectionUtils.isEmpty(boxupDetailVOS)) {
                    deliveryReceiptDO.setCommitType(1);

                    //判断装箱完的是否全部发货
                    if (CollectionUtils.isNotEmpty(boxupMainDOS)) {
                        boolean statusFlag = boxupMainDOS.stream().allMatch(mainDO -> mainDO.getDeliveryStatus() == 1);
                        if (statusFlag) {
                            deliveryReceiptDO.setDeliveryStatus(DeliveryReceiptEnum.DeliveryStatus.Delivered.toString());
                        } else {
                            deliveryReceiptDO.setDeliveryStatus(DeliveryReceiptEnum.DeliveryStatus.PartDelivered.toString());//部分发货
                        }
                    }
                } else {
                    deliveryReceiptDO.setCommitType(0);
                    deliveryReceiptDO.setDeliveryStatus(DeliveryReceiptEnum.DeliveryStatus.PartDelivered.toString());//部分发货
                }
            }

            DataDictionaryDO deliveryDataDictionaryDO = dataDictionaryMapper.itemByCode(DeliveryReceiptEnum.DeliveryStatus.Name.toString(), deliveryReceiptDO.getDeliveryStatus());
            String deliveryStatusDesc = "已发货";
            if (deliveryDataDictionaryDO != null) {
                deliveryStatusDesc = deliveryDataDictionaryDO.getName();
            }
            deliveryReceiptDO.setDeliveryDesc(deliveryStatusDesc);
            deliveryReceiptMapper.update(deliveryReceiptDO);

            //更新装箱表
            boxupMainMapper.updateByReceiptId(deliveryReceiptDO.getId());

            dealSwyThreeGuaBill(deliveryReceiptDO);
//            synLdThreePurchaseStatus(deliveryReceiptDO, orgId);
        }


        return ErrorCode.Success;
    }

    /**
     * @Description 履带吊 调用crm接口推送申请单的状态
     * @Author wzy
     * @Date 2020/9/26
     * @Time 14:56
     */
//    private void synLdThreePurchaseStatus(DeliveryReceiptDO deliveryReceiptDO, String orgId) {
//        LogHelper.monitor("确认发货同步数据到crm开始");
//        //判断如果公司是履带吊则进行推送，如果不是则直接返回
//        String sapCode = companyInfoMapper.getSapCodeByOrgId(orgId);
//        if (sapCode == null || !sapCode.equals(OrgSapCodeEnum.LVDAIDIAO.sapCode)) {
//            LogHelper.monitor("确认发货同步数据到crm公司编码为" + sapCode + "不是履带吊的" + OrgSapCodeEnum.LVDAIDIAO.sapCode);
//            return;
//        }
//        // 判断发运交接单的物流状态为已发货，且订单为三包出库单则想履带吊的crm推送申请状态
//        if (deliveryReceiptDO.getDeliveryStatus().equals(DeliveryReceiptEnum.DeliveryStatus.Delivered.toString())
//                && StringUtils.equals(deliveryReceiptDO.getBillType(), "XGSC")) {
//            try {
//                List<String> names = deliveryReceiptMapper.selectNumbers(deliveryReceiptDO.getBillNo(), orgId);
//                LogHelper.monitor("查询到需要推送的订单编号有" + JSON.toJSONString(names));
//                // 设置时间的格式
//                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//                String shiptime = formatter.format(deliveryReceiptDO.getDeliveryDate());
//                String shipment = deliveryReceiptDO.getShippingMethod();
//                if (names.size() > 0) {
//                    for (String name : names) {
//                        Map paramJO = new HashMap();
//                        paramJO.put("name", name);
//                        paramJO.put("formstatus", "已发货");
//                        paramJO.put("shiptime", shiptime);
//                        paramJO.put("transitmethod", shipment);
//                        Date arrivalDate = deliveryReceiptDO.getArrivalDate();
//                        if (arrivalDate != null) {
//                            String arrivalDateStr = formatter.format(arrivalDate);
//                            paramJO.put("arrivalTime", arrivalDateStr);
//                        }
//                        String inJson = JSON.toJSONString(paramJO);
//                        LogHelper.monitor("调用CRM--PMS_CRM_LdRegionAllotServiceFeedBack接口开始,参数为:" + inJson);
//                        PMSWebService service = new PMSWebService(ldCrmWebserviceUrl);
//                        PMSWebServiceSoap pmsWebServiceSoap = service.getPMSWebServiceSoap();
//                        String result = pmsWebServiceSoap.pmsCRMLdRegionAllotServiceFeedBack(inJson);
//                        LogHelper.monitor("调用-PMS_CRM_LdRegionAllotServiceFeedBack结果:" + result);
//                    }
//                }
//            } catch (Exception e) {
//                LogHelper.error(deliveryReceiptDO.getBillNo() + "履带吊推送申请状态异常" + e, ErrorCode.Failure.getCode());
//            }
//        }
//    }

/*    public void ass() {
        DeliveryReceiptDO receiptDO = new DeliveryReceiptDO();
        receiptDO.setOrgId("348796265925967872");
        receiptDO.setBillType("XGSC");
        receiptDO.setId("416512763360182272");
        receiptDO.setBillNo("XGFJ2170202002240001");
        dealSwyThreeGuaBill(receiptDO);
    }*/

    /**
     * 确认发货后通知施维英的某个系统
     *
     * @param deliveryReceiptDO
     */
    private void dealSwyThreeGuaBill(DeliveryReceiptDO deliveryReceiptDO) {
        CompanyInfoDO companyInfoDO = companyInfoMapper.item(deliveryReceiptDO.getOrgId());
        if (!"XGSC".equals(deliveryReceiptDO.getBillType()) || !CompanyUtil.isSWY(companyInfoDO.getSapCode())) {
            return;
        }
        List<BillDetailMaterialsVO> materialsVOS = threeGuaranteesOutDetailMapper.moreBillDetail(deliveryReceiptDO.getId());
        if (CollectionUtils.isEmpty(materialsVOS)) {
            LogHelper.monitor("materialsVOS is empty. deliveryReceiptNo: " + deliveryReceiptDO.getBillNo());
            return;
        }

        for (BillDetailMaterialsVO materialsVO : materialsVOS) {
            ThreeGuaranteesOutDO threeGuaranteesOutDO = threeGuaranteesOutMapper.itemByNo(materialsVO.getBillNo(), deliveryReceiptDO.getOrgId());
            if (null == threeGuaranteesOutDO) {
                LogHelper.monitor("threeGuaranteesOutDO is null. deliveryReceiptNo: " + deliveryReceiptDO.getBillNo() + ",threeGuaOutNo:" + materialsVO.getBillNo() + ",materialsNo:" + materialsVO.getMaterialsNo());
                continue;
            }
            ThreeGuaranteesOutDetailDO outDetailDO = threeGuaranteesOutDetailMapper.findByNo(threeGuaranteesOutDO.getId(), materialsVO.getMaterialsNo());
            if (null == outDetailDO) {
                LogHelper.monitor("outDetailDO is null. deliveryReceiptNo: " + deliveryReceiptDO.getBillNo() + ",threeGuaOutNo:" + materialsVO.getBillNo() + ",materialsNo:" + materialsVO.getMaterialsNo());
                continue;
            }
            informSWY(outDetailDO, threeGuaranteesOutDO.getPurchaseNo(), deliveryReceiptDO.getOrgId());
        }

    }

    public void informSWY(ThreeGuaranteesOutDetailDO detailDO, String purNo, String orgId) {
//        JSONObject object = new JSONObject();
//        try {
//            ThreeGuaranteesPurDO purDO = threeGuaranteesPurMapper.itemByNo(purNo, orgId);
//            ThreeGuaranteesPurDetailDO purDetailDO = threeGuaranteesPurDetailMapper.findByNo(purDO.getId(), detailDO.getMaterialsNo());
//            object.put("new_srv_partsapply_id", purDO.getCrmOrder());
//            object.put("new_code", detailDO.getMaterialsNo());
//            object.put("new_shippedqty", threeGuaranteesOutMapper.countOutQty(detailDO.getMaterialsNo(), purDO.getPurchaseNo()));
//            //object.put("new_despatchdetail", getSWYStatusCode(detailDO.getOutLocationStatus()));
//            object.put("new_despatchdetail", 2);
//            object.put("new_senddate", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
//            object.put("new_price", null == purDetailDO ? null : purDetailDO.getTotalPrice());
//            String result = HttpRequestUtil
//                    .jsonPost("http://10.17.0.57:8087/api/GPS/Partsapplydetail", object.toString());
//            LogHelper.monitor("informSWY result:" + result + "。param json:" + object.toString());
//        } catch (Exception e) {
//            LogHelper.fatal("informSWY is error. jsonData: " + object.toString(), e);
//        }
    }

    /**
     * 备件状态码与施维英状态码对应关系
     * 备件的012分别是未发运、部分发运、已发运，对应的是施维英CRM的132
     *
     * @param statusCode 备件状态码
     * @return 施维英状态码
     */
    private Integer getSWYStatusCode(Integer statusCode) {
        if (statusCode.equals(0)) {
            return 1;
        } else if (statusCode.equals(1)) {
            return 3;
        } else if (statusCode.equals(2)) {
            return 2;
        } else {
            // 若有待续
            return null;
        }
    }

    /**
     * 能确认发货的情况：
     * 1、施维英
     * 2、塔机和随车已出库
     * 3、有装箱数据
     *
     * @param boxupMainDOS
     * @param orgId
     * @return
     */
    private boolean canShipConfirm(List<BoxupMainDO> boxupMainDOS, String orgId, Integer outStatus) {
        CompanyInfoDO companyInfoDO = companyInfoMapper.item(orgId);
        //return CollectionUtils.isNotEmpty(boxupMainDOS) || CompanyUtil.isSWY(companyInfoDO.getSapCode());

        /**
         * 是施维英 允许发货
         */
        if (CompanyUtil.isSWY(companyInfoDO.getSapCode())) {
            return true;
        }

        /**
         * 塔机和随车 已出库允许发货
         */
        if ((CompanyUtil.isSCSapCode(companyInfoDO.getSapCode()) || CompanyUtil.isTJSapCode(companyInfoDO.getSapCode())) && outStatus.equals(2)) {
            return true;
        }

        /**
         * 有装箱数据 允许发货
         */
        if (CollectionUtils.isNotEmpty(boxupMainDOS)) {
            return true;
        }

        return false;
    }

    @Transactional(rollbackFor = Exception.class)
    public ErrorCode confirmReceipt(DeliveryReceiptVO deliveryReceiptVO, String status)
            throws Exception {
        DeliveryReceiptDO deliveryReceiptDO = deliveryReceiptMapper.item(deliveryReceiptVO.getId());
        deliveryReceiptDO.setDeliveryStatus(status);
        DataDictionaryDO deliveryDataDictionaryDO = dataDictionaryMapper.itemByCode(DeliveryReceiptEnum.DeliveryStatus.Name.toString(), deliveryReceiptDO.getDeliveryStatus());
        if (deliveryDataDictionaryDO != null) {
            deliveryReceiptDO.setDeliveryDesc(deliveryDataDictionaryDO.getName());
        }
        deliveryReceiptDO.setReceiveMessage(deliveryReceiptVO.getReceiveMessage());
        deliveryReceiptDO.setReceiveDate(new Date());
        deliveryReceiptDO.setIsAbnormal(deliveryReceiptVO.getIsAbnormal());

        updateRequestSignQty(deliveryReceiptDO.getBillNo());
        return deliveryReceiptMapper.update(deliveryReceiptDO) > 0 ? ErrorCode.Success : ErrorCode.Failure;
    }

    /**
     * 更新采购订单中的签收数量
     *
     * @param deliveryReceiptNo
     * @throws Exception
     */
    private void updateRequestSignQty(String deliveryReceiptNo) throws Exception {
        List<BoxupDetailVO> materialsList = boxupMainService.beenPackList(deliveryReceiptNo);
        if (CollectionUtils.isEmpty(materialsList)) {
            LogHelper.monitor("updateRequestSignQty.materialsList is null");
            return;
        }
        for (BoxupDetailVO detailVO : materialsList) {
            String purchaseNo = "";
            try {

                purchaseNo = deliveryReceiptLinkMapper.getPurchaseNoByBusinessId(deliveryReceiptNo, detailVO.getDeliveryNoteId());
                if (StringUtils.isBlank(purchaseNo)) {
                    continue;
                }

                PurchaseRequestDO purchaseRequestDO = purchaseRequestMapper.itemByBillNo(purchaseNo);
                if (null == purchaseRequestDO) {
                    continue;
                }
                PurchaseRequestDetailDO detailDO = purchaseRequestDetailMapper
                        .findByBillIdAndMaterialNo(purchaseRequestDO.getBillId(),
                                detailVO.getMaterialsNo(), null);
                if (detailDO == null) {
                    continue;
                }
                detailDO.setSignQty(
                        (null == detailDO.getSignQty() ? BigDecimal.ZERO : detailDO.getSignQty())
                                .add(detailVO.getQty()));
                purchaseRequestDetailMapper.update(detailDO);
            } catch (Exception e) {
                LogHelper.fatal("updateRequestSignQty is error. materialsNo:" +
                        detailVO.getMaterialsNo() + ",deliveryReceiptNo:" + deliveryReceiptNo + ",deliveryNoteId:" + detailVO.getDeliveryNoteId() + ",purchaseNo:" + purchaseNo, e);
                throw new Exception(e);
            }
        }
    }

    public List<DeliveryReceiptDetailVO> detalList(String deliveryReceiptNo, String orgId) {
        List<DeliveryReceiptDetailVO> detailVOS = new ArrayList<>();
        DeliveryReceiptDetailVO deliveryReceiptDetailVO;
        //扫描装箱单号
        if (deliveryReceiptNo.startsWith(BillDesc.Boxup.getDesc())) {
            //查询装箱单
            BoxupMainVO mainVO = new BoxupMainVO();
            mainVO.setBoxupNo(deliveryReceiptNo);
            mainVO.setOrgId(orgId);
            List<BoxupMainDO> boxupMainDOS = boxupMainMapper.list(mainVO);
            if (CollectionUtils.isNotEmpty(boxupMainDOS)) {
                deliveryReceiptDetailVO = new DeliveryReceiptDetailVO();
                deliveryReceiptDetailVO.setPackCode(boxupMainDOS.get(0).getPackCode());
                deliveryReceiptDetailVO.setPackDesc(boxupMainDOS.get(0).getPackDesc());
                deliveryReceiptDetailVO.setDeliveryQty(BigDecimal.ONE);
                detailVOS.add(deliveryReceiptDetailVO);
            }
            return detailVOS;
        }
        DeliveryReceiptDO deliveryReceiptDO = deliveryReceiptMapper.itemByNo(deliveryReceiptNo);
        if (deliveryReceiptDO == null) {
            return new ArrayList<>();
        }
        List<DeliveryReceiptDetailDO> detailDOS = deliveryReceiptDetailMapper.detalList(deliveryReceiptDO.getId());
        for (DeliveryReceiptDetailDO detailDO : detailDOS) {
            deliveryReceiptDetailVO = new DeliveryReceiptDetailVO();
            BeanUtils.copyProperties(detailDO, deliveryReceiptDetailVO);
            detailVOS.add(deliveryReceiptDetailVO);
        }
        return detailVOS;
    }

    public List<BoxupMainVO> boxupList(String deliveryReceiptNo, String orgId) {
        BoxupMainVO mainVO = new BoxupMainVO();
        mainVO.setOrgId(orgId);
        //扫描装箱单号
        if (deliveryReceiptNo.startsWith("XGZX")) {
            mainVO.setBoxupNo(deliveryReceiptNo);
        } else {
            mainVO.setDeliveryReceiptNo(deliveryReceiptNo);
        }
        List<BoxupMainDO> mainDOList = boxupMainMapper.list(mainVO);
        //根据boxupNo去重
        mainDOList = mainDOList.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(BoxupMainDO::getBoxupNo))), ArrayList::new));
        List<BoxupMainVO> mainVOList = new ArrayList<>();
        for (BoxupMainDO mainDOs : mainDOList) {
            BoxupMainVO mainVOs = new BoxupMainVO();
            BeanUtils.copyProperties(mainDOs, mainVOs);
            if (StringUtil.isNotEmpty(mainDOs.getPackageSpecId())) {
                PackageSpecDO packageSpecDO = packageSpecService.item(mainDOs.getPackageSpecId(), orgId);
                if (packageSpecDO != null) {
                    mainVOs.setBoxWeight(packageSpecDO.getWeight());
                }
            }
            mainVOList.add(mainVOs);
        }
        return mainVOList;
    }

    public PageCommonVO moreBillDetail(SearchCommonVO<billMaterialsParamVO> condition) {
        PageCommonVO pageCommonVO = new PageCommonVO();
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        List<BillDetailMaterialsVO> voList = new ArrayList<>();
        switch (condition.getFilters().getBillType()) {
            case "XGFT":
                voList = deliveryNoteDetailMapper.moreBillDetail(condition.getFilters().getDeliveryBillId());
                break;
            case "XGSC":
                voList = threeGuaranteesOutDetailMapper.moreBillDetail(condition.getFilters().getDeliveryBillId());
                //拼接实际库存
                threeGuarantOutTypeBillDetailHandle(voList);
                break;
            case "XGQD":
                voList = regionAllotDetailMapper.moreBillDetail(condition.getFilters().getDeliveryBillId());
                break;
            case "XGFC":
                voList = abnormalOutDetailMapper.moreBillDetail(condition.getFilters().getDeliveryBillId());
                break;
            case "XSCK":
                voList = salesOutBillDetailMapper.moreBillDetail(condition.getFilters().getDeliveryBillId());
                break;
        }
        pageCommonVO.setPageInfo(new PageInfo(voList));
        pageCommonVO.setPageInfoList(voList);
        return pageCommonVO;
    }

    /**
     * @Description 发运交接单-->三包出库单类型的数据处理
     * @Author wzy
     * @Date 2020/9/2
     * @Time 10:05
     */
    private void threeGuarantOutTypeBillDetailHandle(List<BillDetailMaterialsVO> voList) {
        //拼接实际库存
        for (BillDetailMaterialsVO material : voList) {
            BigDecimal deliveryQty = material.getDeliveryQty();
            String materialsNo = material.getMaterialsNo();
            String orgId = material.getOrgId();
            String warehouseCode = material.getWarehouseCode();
            if (org.apache.commons.lang3.StringUtils.isAnyEmpty(materialsNo, orgId, warehouseCode)) {
                continue;
            }
            BigDecimal enableNum = warehouseInventoryMapper.findEnableNum(materialsNo, orgId, warehouseCode);
            enableNum = enableNum == null ? BigDecimal.ZERO : enableNum;
            deliveryQty = deliveryQty == null ? BigDecimal.ZERO : deliveryQty;

            //拼接是否缺货
            String outOfStockShow = deliveryQty.compareTo(enableNum) > 0 ? "是" : "否";
            material.setOutOfStockShow(outOfStockShow);
            material.setDeliveryQty(deliveryQty);
            material.setEnableNum(enableNum);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void arrivalTimeAndRemarkEdit(BillDetailArrivalTimeAndBackFactoryDeitVO edit) {
        String outDetailId = edit.getOutDetailId();
        if (StringUtils.isEmpty(outDetailId)) {
            LogHelper.monitor("编辑关联单据详情到货时间缺少必要参数outDetailId");
            return;
        }
        Date arrivalTime = edit.getArrivalTime();
        String remark = edit.getRemark();
        threeGuaranteesOutDetailMapper.updateArrivalTimeAndRemark(outDetailId, arrivalTime, remark);
        updateArrivalTimeAndRemark(outDetailId, arrivalTime, remark);

    }

    @Transactional(rollbackFor = Exception.class)
    public void threeGuaranteesOutArrivalTimeEdit(BillDetailArrivalTimeEditVO edit) {
        String outDetailId = edit.getOutDetailId();
        Date arrivalTime = edit.getArrivalTime();
        if (StringUtils.isEmpty(outDetailId)) {
            LogHelper.monitor("编辑关联单据详情到货时间缺少必要参数outDetailId");
            return;
        }
        //更新三包出库单中的采购预期到货时间
        threeGuaranteesOutDetailMapper.updateArrivalTime(outDetailId, arrivalTime);
        updateReceitptMaterialArrivalTime(outDetailId, arrivalTime);
    }

    /**
     * 根据三包出库单detail编码查询对应点发运交接单-->查询发运交接单的零件表,更新其中是否返厂，主要为了发运交接单导出时使用
     */
    private void updateReceitptMaterialBackFactory(String outDetailId, Integer backFactory) {
        ThreeGuaranteesOutDetailDO detailDO = threeGuaranteesOutDetailMapper.selectById(outDetailId);
        if (detailDO == null) {
            return;
        }
        String guaranteesOutId = detailDO.getGuaranteesOutNo();
        //guaranteesOutNo就是threeGuaranteesOut表的id = ReceiptLink表里的delivety_note_id
        List<DeliveryReceiptLinkDO> receiptLinkDOS = deliveryReceiptLinkMapper.selectByDeliveryNoteId(guaranteesOutId);
        if (CollectionUtils.isEmpty(receiptLinkDOS)) {
            return;
        }
        // ReceiptLink获取delivery_bill_id , 到DELIVERY_RECEIPT_MATERIAL跟delivery_receipt_id+零件编码更新对应记录时间
        String deliveryBillId = receiptLinkDOS.get(0).getDeliveryBillId();
        if (StringUtils.isEmpty(deliveryBillId)) {
            return;
        }
        //根据deliveryBillId+零件编号更新对应到货时间
        String materialsNo = detailDO.getMaterialsNo();
        if (StringUtil.isEmpty(materialsNo) || backFactory == null) {
            return;
        }
        deliveryReceiptMaterialMapper.udpateBackFactory(deliveryBillId, materialsNo, backFactory);
    }

    private void updateArrivalTimeAndRemark(String detailId, Date arrivalTime, String remark) {
        ThreeGuaranteesOutDetailDO detailDO = threeGuaranteesOutDetailMapper.selectById(detailId);
        if (detailDO == null) {
            return;
        }
        String guaranteesOutId = detailDO.getGuaranteesOutNo();
        //guaranteesOutNo就是threeGuaranteesOut表的id = ReceiptLink表里的delivety_note_id
        List<DeliveryReceiptLinkDO> receiptLinkDOS = deliveryReceiptLinkMapper.selectByDeliveryNoteIdNoDel(guaranteesOutId);
        if (CollectionUtils.isEmpty(receiptLinkDOS)) {
            return;
        }
        // ReceiptLink获取delivery_bill_id , 到DELIVERY_RECEIPT_MATERIAL跟delivery_receipt_id+零件编码更新对应记录时间
        String deliveryBillId = receiptLinkDOS.get(0).getDeliveryBillId();
        if (StringUtils.isEmpty(deliveryBillId)) {
            return;
        }
        //根据deliveryBillId+零件编号更新对应到货时间
        String materialsNo = detailDO.getMaterialsNo();
        if (StringUtil.isEmpty(materialsNo)) {
            return;
        }
        deliveryReceiptMaterialMapper.updateArrivalTimeAndRemark(deliveryBillId, materialsNo, arrivalTime, remark);
    }

    /**
     * 根据三包出库单detail编码查询对应点发运交接单-->查询发运交接单的零件表,更新其中的时间，主要为了发运交接单导出时使用
     */
    private void updateReceitptMaterialArrivalTime(String outDetailId, Date arrivalTime) {
        ThreeGuaranteesOutDetailDO detailDO = threeGuaranteesOutDetailMapper.selectById(outDetailId);
        if (detailDO == null) {
            return;
        }
        String guaranteesOutId = detailDO.getGuaranteesOutNo();
        //guaranteesOutNo就是threeGuaranteesOut表的id = ReceiptLink表里的delivety_note_id
        List<DeliveryReceiptLinkDO> receiptLinkDOS = deliveryReceiptLinkMapper.selectByDeliveryNoteId(guaranteesOutId);
        if (CollectionUtils.isEmpty(receiptLinkDOS)) {
            return;
        }
        // ReceiptLink获取delivery_bill_id , 到DELIVERY_RECEIPT_MATERIAL跟delivery_receipt_id+零件编码更新对应记录时间
        String deliveryBillId = receiptLinkDOS.get(0).getDeliveryBillId();
        if (StringUtils.isEmpty(deliveryBillId)) {
            return;
        }
        //根据deliveryBillId+零件编号更新对应到货时间
        String materialsNo = detailDO.getMaterialsNo();
        if (StringUtil.isEmpty(materialsNo) || arrivalTime == null) {
            return;
        }
        deliveryReceiptMaterialMapper.updatePurExpectArrivalTime(deliveryBillId, materialsNo, arrivalTime);
    }

    public void exportBillDetail(billMaterialsParamVO billMaterialsParamVO) throws Exception {
        List<BillDetailMaterialsVO> voList = new ArrayList<>();
        switch (billMaterialsParamVO.getBillType()) {
            case "XGFT":
                voList = deliveryNoteDetailMapper.moreBillDetail(billMaterialsParamVO.getDeliveryBillId());
                break;
            case "XGSC":
                voList = threeGuaranteesOutDetailMapper.moreBillDetail(billMaterialsParamVO.getDeliveryBillId());
                break;
            case "XGQD":
                voList = regionAllotDetailMapper.moreBillDetail(billMaterialsParamVO.getDeliveryBillId());
                break;
            case "XGFC":
                voList = abnormalOutDetailMapper.moreBillDetail(billMaterialsParamVO.getDeliveryBillId());
                break;
            case "XSCK":
                voList = salesOutBillDetailMapper.moreBillDetail(billMaterialsParamVO.getDeliveryBillId());
        }
        billDetailExport(voList);
    }

    private String getCompanyName(String orgId) {
        CompanyInfoVO companyInfoVO = companyInfoService.info(orgId);
        if (companyInfoVO == null) {
            return "";
        }
        return companyInfoVO.getCompanyName();
    }

    public void exportAll(DeliveryReceiptQueryParam queryParam, String userId, String deptId, String orgId) throws Exception {

        //获取仓库配置权限
        WareHousePermission wareHousePermission = relationService.hasMajorWareHousePermission(queryParam.getOrgId(), deptId);
        UserDetailDTO userInfo = authClient.getUserDetail(userId).getValue();
        //当前用户是服务人员
        if (StringUtil.isNotEmpty(userInfo.getIsService()) && "1".equals(userInfo.getIsService())) {
            queryParam.setServiceName(userInfo.getName());
        } else if (!wareHousePermission.isHasPermission()) {
            return;
        } else {
            queryParam.setWarehousePermitList(wareHousePermission.getPermissionWarehouses());
        }
        //PageHelperPlus.startPage(0, 0, "create_date desc");
        queryParam.setBillNosList(xcmg.device.infra.StringUtil.splitList(queryParam.getBillNos()));
        List<DeliveryReceiptDO> deliveryReceiptDOList = deliveryReceiptMapper.listWarehousePermit(queryParam);
        executeExport(deliveryReceiptDOList, orgId);
    }

    public void export(List<String> billIds, String orgId) throws Exception {
        List<DeliveryReceiptDO> deliveryReceiptDOList = new ArrayList<>();
        for (String billId : billIds
        ) {
            DeliveryReceiptDO purchaseRequestDO = deliveryReceiptMapper.item(billId);
            if (purchaseRequestDO == null) {
                continue;
            }
            deliveryReceiptDOList.add(purchaseRequestDO);
        }
        executeExport(deliveryReceiptDOList, orgId);
    }

    private void executeExport(List<DeliveryReceiptDO> voList, String orgId) throws Exception {
        String title = "发运交接单数据导出";
        /*String[] rowsName = new String[]{"序号", "单号", "客户代码", "客户名称", "单据类型", "发运方式", "承运商", "发货日期", "物流状态",
                "创建人", "制单时间", "签收时间", "承诺时间", "调度员", "零件编码", "零件名称", "单位", "数量", "已出库数量", "出库状态", "储位", "保管员"};*/
        //if (voList.get(0).getBillType().equals("XGSC")){
        String[] rowsName = new String[]{"序号", "单号", "客户代码", "客户名称", "单据类型", "发运方式", "承运商", "发货日期", "物流状态",
                "创建人", "制单时间", "签收时间", "承诺时间", "调度员", "零件编码", "零件名称", "单位", "数量", "已出库数量", "出库状态", "储位", "保管员", "服务信息单号",
                "服务网点", "服务人员", "当前库存", "是否缺货", "到货时间", "是否返厂", "备注"};
        //}
        List<Object[]> dataList = new ArrayList<Object[]>();
        //用于标识当前用户是否属于随车
        boolean scFlag = false;
        CompanyInfoVO companyInfoVO = companyInfoService.info(orgId);
        if (companyInfoVO != null) {
            if (StringUtils.equals(CompanyUtil.SC_SAP_CODE, companyInfoVO.getSapCode())) {
                scFlag = true;
            }
        }
        Object[] objs = null;
        for (int i = 0; i < voList.size(); i++) {
            DeliveryReceiptDO e = voList.get(i);
            List<WarehouseDeliveryDetailDO> deliveryDetailDOList = this.listMore(e.getBillType(), e.getBillNo());
            if (ListUtil.isNullOrEmpty(deliveryDetailDOList)) {
                deliveryDetailDOList = new ArrayList<>();
                deliveryDetailDOList.add(new WarehouseDeliveryDetailDO());
            }

            for (WarehouseDeliveryDetailDO detailDO : deliveryDetailDOList) {
                objs = new Object[rowsName.length];
                objs[0] = i + 1;
                objs[1] = e.getBillNo();
                objs[2] = e.getDealerOrgId();
                objs[3] = e.getDealerOrgName();
                objs[4] = getBillDesc(e.getBillType());
                objs[5] = e.getShippingMethod();
                objs[6] = e.getCarrierOrgName();
                objs[7] = DateUtil.formatDate(e.getDeliveryDate());
                objs[8] = e.getDeliveryDesc();
                objs[9] = e.getCreateName();
                objs[10] = DateUtil.formatDateTime(e.getCreateDate());
                objs[11] = e.getReceiveDate() == null ? "" : DateUtil.formatDateTime(e.getReceiveDate());
                objs[12] = e.getCommitmentTime();
                objs[13] = e.getDispatcherName();
                objs[14] = detailDO.getMaterialNo();
                objs[15] = detailDO.getMaterialName();
                objs[16] = detailDO.getUnit();
                objs[17] = detailDO.getAmount();
                objs[18] = detailDO.getRealAmount();
                objs[19] = getOutStatus(detailDO.getStatus());
                objs[20] = detailDO.getLocationCode();
                objs[21] = detailDO.getKeepName();
                if ("XGSC".equals(e.getBillType())) {
                    objs[22] = detailDO.getServiceNo();
                    objs[23] = detailDO.getServiceSite();
                    objs[24] = detailDO.getServiceName();
                    //20200903 九月第一周计划添加三个新增字段，当前库存，是否缺货，采购预计到期时间
                    BigDecimal warehouseEnableNum = detailDO.getWarehouseEnableNum() == null ? BigDecimal.ZERO : detailDO.getWarehouseEnableNum();
                    BigDecimal amount = detailDO.getAmount() == null ? BigDecimal.ZERO : detailDO.getAmount();
                    objs[25] = warehouseEnableNum;
                    String outOfStockShow = amount.compareTo(warehouseEnableNum) > 0 ? "是" : "否";
                    objs[26] = outOfStockShow;
                    Date purExpectArrivalTime = detailDO.getPurExpectArrivalTime();
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                    String expectArrivalTime = purExpectArrivalTime == null ? "" : sdf.format(purExpectArrivalTime);
                    objs[27] = expectArrivalTime;
                    String backFactory = detailDO.getIsReturn();
                    objs[28] = backFactory;
                    //不是随车，取发运单明细中的备注
                    if (!scFlag) {
                        String remark = detailDO.getRemark();
                        objs[29] = remark;
                    }
                }
                //随车取发运单主表中的备注信息
                if (scFlag) {
                    objs[29] = e.getRemark();
                }
                dataList.add(objs);
            }
        }
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }

    private String getOutStatus(Integer status) {
        status = (status == null ? 0 : status);
        String state;
        switch (status) {
            case 0:
                state = "未出库";
                break;
            case 1:
                state = "部分出库";
                break;
            case 2:
                state = "已出库";
                break;
            default:
                state = "未出库";
                break;
        }
        return state;
    }

    private String getBillDesc(String type) {
        String desc = "发货通知单";
        switch (type) {
            case "XGFT":
                desc = "发货通知";
                break;
            case "XGFC":
                desc = "其它出库";
                break;
            case "XGLL":
                desc = "领料单";
                break;
            case "XGQD":
                desc = "区域调拨";
                break;
            case "XGDB":
                desc = "代理商间调拨";
                break;
            case "XGSC":
                desc = "三包出库";
                break;
            case "XSCK":
                desc = "销售出库";
                break;
        }
        return desc;
    }

    private void billDetailExport(List<BillDetailMaterialsVO> voList) throws Exception {
        String title = "发运交接单关联单据详情";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String[] rowsName = new String[]{"序号", "零件编号", "零件名称", "单据号", "储位", "保管员"};
        List<Object[]> dataList = new ArrayList<Object[]>();
        Object[] objs = null;
        for (int i = 0; i < voList.size(); i++) {
            BillDetailMaterialsVO e = voList.get(i);
            objs = new Object[rowsName.length];
            objs[0] = i + 1;
            objs[1] = e.getMaterialsNo();
            objs[2] = e.getMaterialsDes();
            objs[3] = e.getBillNo();
            objs[4] = e.getStockLocation();
            objs[5] = e.getStockUserName();

            dataList.add(objs);
        }
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }

    private List<WarehouseDeliveryDetailDO> listMore(String billType, String billNo) {
        if (StringUtil.isEmpty(billNo)) {
            return new ArrayList<>();
        }
        List<WarehouseDeliveryDetailDO> list = null;
        if (BillDesc.DeliveryNo.getDesc().equals(billType)) {
            list = deliveryReceiptLinkMapper.listForDeliveryNote(billNo);
        }
        if (BillDesc.ThreeOut.getDesc().equals(billType)) {
            list = deliveryReceiptLinkMapper.listForThreeOut(billNo);
        }
        if (BillDesc.RegionAllot.getDesc().equals(billType)) {
            list = deliveryReceiptLinkMapper.listForRegionAllot(billNo);
        }
        if (BillDesc.AbnormalOutNo.getDesc().equals(billType)) {
            list = deliveryReceiptLinkMapper.listForAbnormalOut(billNo);
        }
        if (BillDesc.SalesOutNo.getDesc().equals(billType)) {
            list = deliveryReceiptLinkMapper.listForSalesOut(billNo);
        }
        if (list == null) {
            list = new ArrayList<>();
        }
        return list;
    }

    public ErrorCode delete(String id) throws Exception {
        DeliveryReceiptDO receiptDO = deliveryReceiptMapper.item(id);
        if (receiptDO == null) {
            return ErrorCode.IllegalArument;
        }
        int count = boxupMainMapper.countForReceipt(id);
        if (count > 0) {
            throw new Exception("只能删除未装箱的发运交接单");
        }
        receiptDO.setIsDel(true);
        //更新三日计划交货状态
        List<DeliveryReceiptLinkDO> list = deliveryReceiptLinkMapper.list(id);
        for (DeliveryReceiptLinkDO deliveryReceiptLinkDO : list) {
            updateThreeDayPlanDlvStatus(deliveryReceiptLinkDO.getbId(), 0);
        }
        deliveryReceiptLinkMapper.deleteByDeliveryReceiptId(id);
        //重置发运交接单关联的出库记录中的发运交接单号
        delReceiptResetDeliveryRecordReceiptNo(receiptDO.getBillNo());
        return deliveryReceiptMapper.update(receiptDO) > 0 ? ErrorCode.Success : ErrorCode.Failure;
    }

    /**
     * @Des 删除发运交接单时重置发运交接单关联的出库记录中的发运交接单号
     * @Date 2021/4/21 11:04
     * @Author wangzhaoyu
     * @Param [billNo]
     * @Return void
     */
    private void delReceiptResetDeliveryRecordReceiptNo(String billNo) {
        if (StringUtils.isEmpty(billNo)) {
            return;
        }
        warehouseDeliveryRecordMapper.resetReceiptNo(billNo, null);
    }

    public void exportAllNew(DeliveryReceiptVO condition, String userId, String deptId) throws Exception {
        if (StringUtil.isEmpty(condition.getBillType())) {
            return;
        }
        condition.setBillNosList(xcmg.device.infra.StringUtil.splitList(condition.getBillNos()));

        //UserDetailDTO userInfo = authClient.getUserDetail(userId).getValue();
        //当前用户是服务人员
//        if (StringUtil.isNotEmpty(userInfo.getIsService()) && userInfo.getIsService().equals("1")) {
//            condition.setServiceName(userInfo.getName());
//        }

        UserDetailDTO userInfo = authClient.getUserDetail(userId).getValue();
        //当前用户是服务人员
        if (StringUtil.isNotEmpty(userInfo.getIsService()) && "1".equals(userInfo.getIsService())) {
            condition.setServiceName(userInfo.getName());
        } else {
            //获取仓库配置权限
            WareHousePermission wareHousePermission = relationService.hasMajorWareHousePermission(condition.getOrgId(), deptId);
            if (!wareHousePermission.isHasPermission()) {
                return;
            } else {
                condition.setWarehousePermitList(wareHousePermission.getPermissionWarehouses());
            }
        }

        int count = this.exportAllNewCount(condition);
        int times = count / 500 + 1;
        List<DeliveryReceiptExportDO> dataList = new ArrayList<>();
        for (int i = 0; i < times; i++) {
            PageHelperPlus.startPage(i + 1, 500, "T1.CREATE_DATE DESC");
            switch (condition.getBillType()) {
                case "XGFT":
                    dataList.addAll(deliveryReceiptMapper.listForExportDelivery(condition));
                    break;
                case "XGSC":
                    dataList.addAll(deliveryReceiptMapper.listForExportThree(condition));
                    break;
                case "XGQD":
                    dataList.addAll(deliveryReceiptMapper.listForExportRegion(condition));
                    break;
                case "XGFC":
                    dataList.addAll(deliveryReceiptMapper.listForExportAbnormal(condition));
                    break;
            }
        }
        invokeExport(dataList);
    }

    private int exportAllNewCount(DeliveryReceiptVO condition) {
        int count = 0;
        switch (condition.getBillType()) {
            case "XGFT":
                count = deliveryReceiptMapper.listCountForExportDelivery(condition);
                return count;
            case "XGSC":
                count = deliveryReceiptMapper.listCountForExportThree(condition);
                return count;
            case "XGQD":
                count = deliveryReceiptMapper.listCountForExportRegion(condition);
                return count;
            case "XGFC":
                count = deliveryReceiptMapper.listCountForExportAbnormal(condition);
                return count;
        }
        return count;
    }

    private void invokeExport(List<DeliveryReceiptExportDO> doList) throws Exception {
        String title = "发运交接单数据导出";
        String[] rowsName = new String[]{"序号", "发运交接单号", "代理商采购单号", "意向单号", "发货通知单号",
                "客户名称", "单据类型", "发运方式", "承运商", "发货日期", "物流状态", "创建人", "制单时间",
                "签收时间", "承诺时间", "调度员", "零件编码", "零件名称", "单位", "数量", "已出库数量", "单价", "金额", "出库状态", "服务信息单号", "服务站点", "服务人员"};
        List<Object[]> dataList = new ArrayList<Object[]>();
        Object[] objs;
        for (int i = 0; i < doList.size(); i++) {
            DeliveryReceiptExportDO exportDO = doList.get(i);
            objs = new Object[rowsName.length];
            objs[0] = i + 1;
            objs[1] = exportDO.getBillNo();
            objs[2] = exportDO.getPurchaseNo();
            objs[3] = exportDO.getSaleNo();
            objs[4] = exportDO.getDeliveryNo();
            objs[5] = exportDO.getDealerOrgName();
            objs[6] = getBillDesc(exportDO.getBillType());
            objs[7] = exportDO.getShippingMethod();
            objs[8] = exportDO.getCarrierOrgName();
            objs[9] = DateUtil.formatDate(exportDO.getDeliveryDate());
            objs[10] = exportDO.getDeliveryDesc();
            objs[11] = exportDO.getCreateName();
            objs[12] = DateUtil.formatDateTime(exportDO.getCreateDate());
            objs[13] = DateUtil.formatDateTime(exportDO.getReceiveDate());
            objs[14] = exportDO.getCommitmentTime();
            objs[15] = exportDO.getDispatcherName();
            objs[16] = exportDO.getMaterialsNo();
            objs[17] = exportDO.getMaterialsDes();
            objs[18] = exportDO.getUnit();
            objs[19] = exportDO.getQty();
            objs[20] = exportDO.getOutQty();
            objs[21] = DecimalUtil.roundDecimal4Output(exportDO.getPrice());
            objs[22] = DecimalUtil.roundDecimal4Output(exportDO.getTotalPrice());
            objs[23] = getOutStatus(exportDO.getOutStatus());
            objs[24] = exportDO.getServiceNo();
            objs[25] = exportDO.getServiceSite();
            objs[26] = exportDO.getServiceName();
            dataList.add(objs);
        }
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }

    public String uploadAttach(MultipartFile file, String id) {
        DeliveryReceiptDO deliveryReceiptDO = deliveryReceiptMapper.item(id);
        if (deliveryReceiptDO == null) {
            return null;
        }
        boolean success = deliveryReceiptMapper.updateAttachName(file.getOriginalFilename(), id) > 0;
        if (!success) {
            return null;
        }
        try {
            String fileName = id + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
            FileUtil.uploadFile(file, filePath + "delivery_receipt_attach/", fileName);
        } catch (Exception e) {
            return "";
        }
        return file.getOriginalFilename();
    }

    public void downloadAttach(String id) throws Exception {
        DeliveryReceiptDO deliveryReceiptDO = deliveryReceiptMapper.item(id);
        if (deliveryReceiptDO == null || StringUtils.isBlank(deliveryReceiptDO.getAttachName())) {
            return;
        }
        String fileType = StringUtils.substring(deliveryReceiptDO.getAttachName(), deliveryReceiptDO.getAttachName().lastIndexOf("."));
        FileUtil.downLoadFile(response, filePath + "delivery_receipt_attach/", id + fileType);
    }

    /**
     * 判断是否是需要自动生成发运交接单的主机厂
     *
     * @param supplierOrgId
     * @return
     */
    private boolean isAutoGenRecetipCom(String supplierOrgId) {
        List<SystemParameter> autoGenRecetipComs = systemParameterService.listByParamType(AUTO_GEN_RECEIPT_SUPPLIER);
        return containsParam(autoGenRecetipComs, supplierOrgId);
    }

    /**
     * 判断是否是不需要自动生成发运交接单的客户
     *
     * @param supplierOrgId
     * @param purchaseOrgId
     * @return
     */
    private boolean isNotAutoGenRecetipDealer(String supplierOrgId, String purchaseOrgId) {
        List<SystemParameter> notAutoGenRecetipDealers = systemParameterService.listByParamType(NOT_AUTO_RECEIPT_DEALER, supplierOrgId);
        return containsParam(notAutoGenRecetipDealers, purchaseOrgId);
    }

    private boolean containsParam(List<SystemParameter> sourceParameters, String target) {
        if (CollectionUtils.isEmpty(sourceParameters)) {
            return false;
        }
        for (SystemParameter parameter : sourceParameters) {
            if (target.equals(parameter.getParamValue())) {
                return true;
            }
        }
        return false;
    }

    /**
     * @Author: WangKe
     * @Description: 挖机紧急订单自动生成运单, 进出口与智联不计入
     * @Date: 2019/1/25 0025
     */
    public void addByDeliveryNote(DeliveryNoteDO deliveryNoteDO) throws Exception {
        if (deliveryNoteDO == null || !"1".equals(deliveryNoteDO.getStatus()) || !"1".equals(deliveryNoteDO.getPurchaseLevelId())) {
            return;
        }
//        if (!CompanyUtil.isWJ(deliveryNoteDO.getSupplierOrgId())
//                || StringUtils.equals(deliveryNoteDO.getPurchaseOrgName(), CompanyUtil.IMPORT_EXPORT_COM_NAME)
//                || StringUtils.equals(deliveryNoteDO.getPurchaseOrgName(), CompanyUtil.ZL_COM_NAME)) {
//            return;
//        }

        if (!isAutoGenRecetipCom(deliveryNoteDO.getSupplierOrgId())) {
            return;
        }
        if (isNotAutoGenRecetipDealer(deliveryNoteDO.getSupplierOrgId(), deliveryNoteDO.getPurchaseOrgId())) {
            return;
        }

        SaleIntentionDO saleIntentionDO = saleIntentionMapper.itemByNo(deliveryNoteDO.getSaleNo(), deliveryNoteDO.getSupplierOrgId());
        if (saleIntentionDO == null) {
            LogHelper.error(deliveryNoteDO.getSaleNo() + "未找到销售单", ErrorCode.Failure.getCode());
            return;
        }
        PurchaseRequestDO purchaseRequestDO = purchaseRequestMapper.itemByPurchase(saleIntentionDO.getPurchaseNo(), saleIntentionDO.getPurchaseOrgId());

        OperateDeliveryReceiptVO operateDeliveryReceiptVO = new OperateDeliveryReceiptVO();
        List<DeliveryReceiptLinkVO> billList = new ArrayList<>();
        DeliveryReceiptLinkVO receiptLinkVO = new DeliveryReceiptLinkVO();
        String billType = StringUtils.substring(deliveryNoteDO.getDeliveryNo(), 0, 4);
        receiptLinkVO.setBillType(billType);
        receiptLinkVO.setDeliveryNoteId(deliveryNoteDO.getId());
        receiptLinkVO.setDeliveryNoteNo(deliveryNoteDO.getDeliveryNo());
        receiptLinkVO.setSaleBillNo(deliveryNoteDO.getDeliveryNo());
        if (purchaseRequestDO != null) {
            receiptLinkVO.setPurchaseBillId(purchaseRequestDO.getBillId());
            receiptLinkVO.setPurchaseBillNo(purchaseRequestDO.getBillNo());
        }
        billList.add(receiptLinkVO);
        operateDeliveryReceiptVO.setBillList(billList);

        DeliveryReceiptVO deliveryReceiptVO = new DeliveryReceiptVO();
        deliveryReceiptVO.setOrgId(deliveryNoteDO.getSupplierOrgId());
        deliveryReceiptVO.setOrgName(deliveryNoteDO.getSupplierOrgName());
        deliveryReceiptVO.setReceiverAddress(deliveryNoteDO.getAddress());
        deliveryReceiptVO.setBillType(billType);
        deliveryReceiptVO.setCreateId(deliveryNoteDO.getSupplierOrgId());
        deliveryReceiptVO.setUpdateId(deliveryNoteDO.getSupplierOrgId());
        deliveryReceiptVO.setCreateName("管理员");
        deliveryReceiptVO.setDispatcherName(deliveryNoteDO.getCreateName());
        deliveryReceiptVO.setDealerOrgId(deliveryNoteDO.getPurchaseOrgId());
        deliveryReceiptVO.setDealerOrgName(deliveryNoteDO.getPurchaseOrgName());
        deliveryReceiptVO.setReceiverName(deliveryNoteDO.getReceiverName());
        deliveryReceiptVO.setReceiverFax(deliveryNoteDO.getReceiverFax());
        deliveryReceiptVO.setReceiverTel(deliveryNoteDO.getReceiverPhone());
        deliveryReceiptVO.setSettlementId(ARRIVED_PAY);
        deliveryReceiptVO.setSettlementDesc("到付");
        deliveryReceiptVO.setShippingMethod(deliveryNoteDO.getDeliveryTypeName());
        deliveryReceiptVO.setShippingMethodId(deliveryNoteDO.getDeliveryTypeId());
        deliveryReceiptVO.setShippingSecondMethod(deliveryNoteDO.getSendTypeChildName());
        deliveryReceiptVO.setShippingSecondMethodId(deliveryNoteDO.getSendTypeChildId());
        deliveryReceiptVO.setDeliveryDate(new Date());
        operateDeliveryReceiptVO.setDeliveryReceiptVO(deliveryReceiptVO);

        this.add(operateDeliveryReceiptVO);
    }

    /**
     * 根据采购单号查询对应的发运交接单的物流状态
     *
     * @param purchaseNo
     * @param sapCode
     * @return
     * @throws Exception
     */
    public List<DeliveryStatusVO> listStatusByPurchaseNo(String purchaseNo, String sapCode) throws Exception {
        CompanyInfoDO companyInfoDO = companyInfoMapper.itemBySap(sapCode);
        if (null == companyInfoDO) {
            throw new Exception("未查询到该公司");
        }
        PurchaseRequestDO purchaseRequestDO = purchaseRequestMapper.itemByBillNo(purchaseNo);
        if (null == purchaseRequestDO || !companyInfoDO.getOrgId().equals(purchaseRequestDO.getSupplierOrgId())) {
            throw new Exception("未查询到该采购订单");
        }
        return deliveryReceiptLinkMapper.listStatusByPurchaseNo(purchaseNo);
    }

    private static final Integer ARRIVAL_FLAG_YES = 1;

    /**
     * 更新到货时间
     *
     * @param id
     * @param arrivalDate
     */
    public boolean updateArrivalDate(String id, Date arrivalDate) {
        DeliveryReceiptDO deliveryReceiptDO = new DeliveryReceiptDO();
        deliveryReceiptDO.setId(id);
        deliveryReceiptDO.setRealArrivalDate(arrivalDate);
        deliveryReceiptDO.setArrivalFlag(ARRIVAL_FLAG_YES);
        return deliveryReceiptMapper.update(deliveryReceiptDO) > 0;
    }

    public List<DeliveryReceiptDO> list4ExpressInfo(String serviceNo, String receiverName, String receiverTel) {
        return deliveryReceiptMapper.list4ExpressInfo(serviceNo, receiverName, receiverTel);
    }

    public BigDecimal getFreight(String logisticsBasicId, BigDecimal totalWeight) {
        if (StringUtil.isEmpty(logisticsBasicId) || totalWeight == null) {
            return BigDecimal.ZERO;
        }
        LogisticsBasicDataVO logisticsBasicDataVO = logisticsBasicDataService.item(logisticsBasicId);
        if (logisticsBasicDataVO == null) {
            return BigDecimal.ZERO;
        }
        if (totalWeight.compareTo(logisticsBasicDataVO.getFirstWeight()) < 1) {
            return logisticsBasicDataVO.getFirstAmount();
        }

        List<LogisticsBasicWeightDO> list = logisticsBasicDataVO.getList();
        if (list == null || list.size() == 0) {
            return logisticsBasicDataVO.getFirstAmount();
        }
//        list.sort(Comparator.comparing(LogisticsBasicWeightDO::getWeightStart));

        BigDecimal freight = logisticsBasicDataVO.getFirstAmount();
        for (LogisticsBasicWeightDO logisticsBasicWeightDO : list) {
//            if (totalWeight.compareTo(logisticsBasicWeightDO.getWeightEnd()) == 1) {
//                freight = freight.add(logisticsBasicWeightDO.getWeightEnd().subtract(logisticsBasicWeightDO.getWeightStart()).multiply(logisticsBasicWeightDO.getUnitPrice()).add(logisticsBasicWeightDO.getAdditional()));
//            }
            if (totalWeight.compareTo(logisticsBasicWeightDO.getWeightStart()) == 1 && totalWeight.compareTo(logisticsBasicWeightDO.getWeightEnd()) < 1) {
                freight = freight.add(totalWeight.subtract(logisticsBasicDataVO.getFirstWeight()).multiply(logisticsBasicWeightDO.getUnitPrice()).add(logisticsBasicWeightDO.getAdditional()));
            }
        }
        return freight;
    }


    /**
     * 进出口获取打印详情
     *
     * @param billId
     * @return
     */
    public List<PrintDeliveryReceiptVO> item4Print(String billId) throws Exception {
        DeliveryReceiptDO deliveryReceiptDO = deliveryReceiptMapper.item(billId);
        if (deliveryReceiptDO == null) {
            return null;
        }
        String billNo = deliveryReceiptDO.getBillNo();

        List<PrintDeliveryReceiptVO> receiptVOList = Lists.newArrayList();
        PrintDeliveryReceiptVO printDeliveryReceiptVO;

        //装箱列表
        String orgId = deliveryReceiptDO.getOrgId();
        BoxupMainVO mainVO = new BoxupMainVO();
        mainVO.setDeliveryReceiptId(deliveryReceiptDO.getId());
        mainVO.setDeliveryReceiptNo(billNo);
        mainVO.setOrgId(orgId);//限制只查自己，防止同步装箱出问题
        List<BoxupMainDO> mainDOList = boxupMainMapper.list(mainVO);
        if (CollectionUtils.isNotEmpty(mainDOList)) {

            Map<String, List<BoxupMainDO>> mainDOMap = mainDOList.stream().collect(Collectors.groupingBy(BoxupMainDO::getBoxupNo));

            //查询装箱实际占用的箱子编号
            List<String> boxupNos = mainDOList.stream().map(BoxupMainDO::getBoxupNo).distinct().collect(Collectors.toList());

            //根据boxupNos查询全部交接单号
            BoxupMainVO boxupMainVO = new BoxupMainVO();
            boxupMainVO.setOrgId(orgId);
            boxupMainVO.setBoxupNoList(boxupNos);
            List<BoxupMainDO> mainDOs = boxupMainMapper.list(boxupMainVO);

            //查询关联的交接单号
            List<String> billIds = mainDOs.stream().map(BoxupMainDO::getDeliveryReceiptId).distinct().collect(Collectors.toList());

            //查询关联的发货通知单
            List<DeliveryReceiptLinkDO> billDOList = deliveryReceiptLinkMapper.listAll(billIds);
            List<String> deliveryNoteIds = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(billDOList)) {
                deliveryNoteIds = billDOList.stream().map(DeliveryReceiptLinkDO::getDeliveryNoteId).distinct().collect(Collectors.toList());
            }

            //查询发货通知单列表
            DeliveryNoteVO deliveryNoteVO = new DeliveryNoteVO();
            deliveryNoteVO.setIds(deliveryNoteIds);
            List<DeliveryNoteDO> deliveryNoteDOList = deliveryNoteMapper.list(deliveryNoteVO);
            Map<String, DeliveryNoteDO> deliveryNoteDOMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(deliveryNoteDOList)) {
                deliveryNoteDOMap = deliveryNoteDOList.stream().collect(Collectors.toMap(DeliveryNoteDO::getId, Function.identity(), (k1, k2) -> k2));
            }

            //发货通知单详情
            List<DeliveryNoteDetailDO> deliveryNoteDetailDOList = deliveryNoteDetailMapper.listByDeliveryNoteIds(deliveryNoteIds);
            Map<String, List<DeliveryNoteDetailDO>> detailDOMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(deliveryNoteDetailDOList)) {
                detailDOMap = deliveryNoteDetailDOList.stream().collect(Collectors.groupingBy(DeliveryNoteDetailDO::getMaterialsNo));
            }

            //装箱详情
            List<BoxupDetailDO> materialsList = boxupDetailMapper.listByBoxupNos(boxupNos, deliveryNoteIds);

            Map<String, List<BoxupDetailDO>> boxupDetailMap = new HashMap<>();
            Map<String, PubMaterialsDO> pubMaterialsDOMap = new HashMap<>();
            List<String> materialsNos = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(materialsList)) {
                boxupDetailMap = materialsList.stream().collect(Collectors.groupingBy(BoxupDetailDO::getBoxupNo));
                materialsNos = materialsList.stream().map(BoxupDetailDO::getMaterialsNo).distinct().collect(Collectors.toList());
                List<PubMaterialsDO> pubMaterialsDOList = pubMaterialsMapper.selectByMaterialsNos(materialsNos);
                if (CollectionUtils.isNotEmpty(pubMaterialsDOList)) {
                    pubMaterialsDOMap = pubMaterialsDOList.stream().collect(Collectors.toMap(PubMaterialsDO::getMaterialsNo, Function.identity(), (k1, k2) -> k2));
                }
            }
            for (int i = 0; i < boxupNos.size(); i++) {
                BoxupMainDO mainDO = mainDOMap.get(boxupNos.get(i)).get(0);
                printDeliveryReceiptVO = new PrintDeliveryReceiptVO();
                BeanUtils.copyProperties(mainDO, printDeliveryReceiptVO);
                printDeliveryReceiptVO.setBillNo(billNo);//交接单号
                printDeliveryReceiptVO.setCheckerName(deliveryReceiptDO.getCheckerName());//验箱人
                if (boxupDetailMap.containsKey(mainDO.getBoxupNo())) {
                    List<PrintDeliveryReceiptDetailVO> detailVOList = Lists.newArrayList();
                    List<BoxupDetailDO> boxupDetailDOList = boxupDetailMap.get(mainDO.getBoxupNo());

                    PrintDeliveryReceiptDetailVO printDeliveryReceiptDetailVO;
                    for (BoxupDetailDO boxupDetailDO : boxupDetailDOList) {
                        String materialsNo = boxupDetailDO.getMaterialsNo();
                        printDeliveryReceiptDetailVO = new PrintDeliveryReceiptDetailVO();
                        BeanUtils.copyProperties(boxupDetailDO, printDeliveryReceiptDetailVO);
                        if (billNo.startsWith("XGJK")) {//进出口运单
                            BarcodeManageDO barcodeDO = barcodeManageMapper.item(boxupDetailDO.getBarcode(), mainDO.getOrgId());
                            if (StringUtils.isEmpty(barcodeDO.getPurchaseContractNo())) {
                                throw new Exception("零件【" + materialsNo + "】--条码【" + boxupDetailDO.getBarcode() + "】对应批次号（采购订单号）不能为空");
                            }
                            printDeliveryReceiptDetailVO.setPurchaseContractNo(barcodeDO.getPurchaseContractNo());//采购合同编号
                            printDeliveryReceiptDetailVO.setMachineModel(barcodeDO.getMachineModel());//机型
                            if (StringUtils.isEmpty(printDeliveryReceiptVO.getCountry())) {
                                printDeliveryReceiptVO.setCountry(barcodeDO.getCountry());//国家
                            }

                            if (detailDOMap.containsKey(materialsNo)) {
                                Optional<DeliveryNoteDetailDO> noteDetailDOOptional = detailDOMap.get(materialsNo).stream().filter(item -> StringUtils.isNotBlank(item.getOriginalMaterialsNo())).findFirst();
                                if (noteDetailDOOptional.isPresent()) {
                                    printDeliveryReceiptDetailVO.setOriginalMaterialsNo(noteDetailDOOptional.get().getOriginalMaterialsNo());
                                }
                            }

                        } else {//进出口发运交接单
                            if (deliveryNoteDOMap.containsKey(boxupDetailDO.getDeliveryNoteId())) {
                                DeliveryNoteDO deliveryNoteDO = deliveryNoteDOMap.get(boxupDetailDO.getDeliveryNoteId());
                                if (StringUtils.isEmpty(deliveryNoteDO.getPurchaseContractNo())) {
                                    throw new Exception("零件【" + materialsNo + "】对应批次号（采购订单号）不能为空");
                                }

                                printDeliveryReceiptDetailVO.setPurchaseContractNo(deliveryNoteDO.getPurchaseContractNo());//采购合同编号
                                if (StringUtils.isEmpty(printDeliveryReceiptVO.getCountry())) {
                                    printDeliveryReceiptVO.setCountry(deliveryNoteDO.getCountry());//国家
                                }

                                //机型 原零件号
                                if (detailDOMap.containsKey(materialsNo)) {
                                    //过滤同一发货通知单
                                    List<DeliveryNoteDetailDO> noteDetailDOS = detailDOMap.get(materialsNo).stream()
                                            .filter(n -> n.getDeliveryNoteNo().equals(deliveryNoteDO.getId())).collect(Collectors.toList());
                                    if (CollectionUtils.isNotEmpty(noteDetailDOS)) {
                                        printDeliveryReceiptDetailVO.setMachineModel(noteDetailDOS.get(0).getMachineModel());
                                    } else {
                                        //日志追踪
                                        log.info("*****************零件号【" + materialsNo + "】装箱单中通知单号不一致**************");
                                        if (deliveryNoteDO.getId() != null) {
                                            log.info("****************装箱单详情中发货通知单号【" + deliveryNoteDO.getId() + "】********");
                                        }
                                    }

                                    Optional<DeliveryNoteDetailDO> noteDetailDOOptional = detailDOMap.get(materialsNo).stream().filter(item -> StringUtils.isNotBlank(item.getOriginalMaterialsNo())).findFirst();
                                    if (noteDetailDOOptional.isPresent()) {
                                        printDeliveryReceiptDetailVO.setOriginalMaterialsNo(noteDetailDOOptional.get().getOriginalMaterialsNo());
                                    }
                                }
                            }
                        }

                        printDeliveryReceiptDetailVO.setMaterialsDesCN(boxupDetailDO.getMaterialsDes());
                        //英文描述
                        if (pubMaterialsDOMap.containsKey(materialsNo)) {
                            printDeliveryReceiptDetailVO.setMaterialsDesEN(pubMaterialsDOMap.get(materialsNo).getMaterialsDesEn());
                        }
                        detailVOList.add(printDeliveryReceiptDetailVO);
                    }

                    //合并相同采购合同号，零件号
                    Map<String, Map<String, List<PrintDeliveryReceiptDetailVO>>> groupMap = detailVOList.stream().collect(
                            Collectors.groupingBy(PrintDeliveryReceiptDetailVO::getPurchaseContractNo,
                                    Collectors.groupingBy(PrintDeliveryReceiptDetailVO::getMaterialsNo)));

                    List<PrintDeliveryReceiptDetailVO> materialsNOList = Lists.newArrayList();
                    for (Map.Entry<String, Map<String, List<PrintDeliveryReceiptDetailVO>>> groupEntry : groupMap.entrySet()) {
                        for (Map.Entry<String, List<PrintDeliveryReceiptDetailVO>> entry : groupEntry.getValue().entrySet()) {
                            printDeliveryReceiptDetailVO = new PrintDeliveryReceiptDetailVO();
                            printDeliveryReceiptDetailVO.setPurchaseContractNo(groupEntry.getKey());

                            printDeliveryReceiptDetailVO.setMaterialsNo(entry.getKey());
                            List<PrintDeliveryReceiptDetailVO> deliveryReceiptDetailVOS = entry.getValue();
                            BigDecimal totalAmount = deliveryReceiptDetailVOS.stream().map(PrintDeliveryReceiptDetailVO::getQty)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            printDeliveryReceiptDetailVO.setQty(totalAmount);
                            printDeliveryReceiptDetailVO.setMaterialsDesEN(deliveryReceiptDetailVOS.get(0).getMaterialsDesEN());
                            printDeliveryReceiptDetailVO.setMaterialsDesCN(deliveryReceiptDetailVOS.get(0).getMaterialsDesCN());
                            printDeliveryReceiptDetailVO.setMachineModel(deliveryReceiptDetailVOS.get(0).getMachineModel());
                            printDeliveryReceiptDetailVO.setOriginalMaterialsNo(deliveryReceiptDetailVOS.get(0).getOriginalMaterialsNo());
                            materialsNOList.add(printDeliveryReceiptDetailVO);
                        }
                    }

                    printDeliveryReceiptVO.setMaterialsList(materialsNOList);
                }
                receiptVOList.add(printDeliveryReceiptVO);
            }
        }

        //箱号按装箱时间排序
        if (CollectionUtils.isNotEmpty(receiptVOList)) {
            List<PrintDeliveryReceiptVO> sortList = receiptVOList.stream().sorted(Comparator.comparing(PrintDeliveryReceiptVO::getCreateTime))
                    .collect(Collectors.toList());
            for (int i = 0; i < sortList.size(); i++) {
                // 箱号按照装箱顺序
                sortList.get(i).setBoxNo(i + 1);//箱号
            }
            return sortList;
        }

        return receiptVOList;
    }

    /**
     * 批量获取进出口打印详情
     *
     * @param billIdList
     * @return
     */
    public List<PrintDeliveryReceiptVO> batch4Print(List<String> billIdList, String orgId) throws Exception {
        List<DeliveryReceiptDO> deliveryReceiptDOList = deliveryReceiptMapper.itemByIds(billIdList);
        if (CollectionUtils.isEmpty(deliveryReceiptDOList)) {
            return null;
        }

        Map<String, DeliveryReceiptDO> receiptDOMap = deliveryReceiptDOList.stream().collect(
                Collectors.toMap(DeliveryReceiptDO::getBillNo, Function.identity(), (k1, k2) -> k2));

        List<PrintDeliveryReceiptVO> receiptVOList = Lists.newArrayList();
        PrintDeliveryReceiptVO printDeliveryReceiptVO;

        //装箱列表
        BoxupMainVO mainVO = new BoxupMainVO();
        mainVO.setDeliveryReceiptIdList(billIdList);
        mainVO.setOrgId(orgId);//限制只查自己，防止同步装箱出问题
        List<BoxupMainDO> mainDOList = boxupMainMapper.list(mainVO);
        if (CollectionUtils.isNotEmpty(mainDOList)) {

            Map<String, List<BoxupMainDO>> mainDOMap = mainDOList.stream().collect(Collectors.groupingBy(BoxupMainDO::getBoxupNo));
            //查询装箱实际占用的箱子编号
            List<String> boxupNos = mainDOList.stream().map(BoxupMainDO::getBoxupNo).distinct().collect(Collectors.toList());

            //根据boxupNos查询全部交接单号
            BoxupMainVO boxupMainVO = new BoxupMainVO();
            boxupMainVO.setOrgId(orgId);
            boxupMainVO.setBoxupNoList(boxupNos);
            List<BoxupMainDO> mainDOs = boxupMainMapper.list(boxupMainVO);

            //查询关联的交接单号
            List<String> billIds = mainDOs.stream().map(BoxupMainDO::getDeliveryReceiptId).distinct().collect(Collectors.toList());

            //查询关联的发货通知单
            List<DeliveryReceiptLinkDO> billDOList = deliveryReceiptLinkMapper.listAll(billIds);
            List<String> deliveryNoteIds = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(billDOList)) {
                deliveryNoteIds = billDOList.stream().map(DeliveryReceiptLinkDO::getDeliveryNoteId).distinct().collect(Collectors.toList());
            }

            //查询发货通知单列表
            DeliveryNoteVO deliveryNoteVO = new DeliveryNoteVO();
            deliveryNoteVO.setIds(deliveryNoteIds);
            List<DeliveryNoteDO> deliveryNoteDOList = deliveryNoteMapper.list(deliveryNoteVO);
            Map<String, DeliveryNoteDO> deliveryNoteDOMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(deliveryNoteDOList)) {
                deliveryNoteDOMap = deliveryNoteDOList.stream().collect(Collectors.toMap(DeliveryNoteDO::getId, Function.identity(), (k1, k2) -> k2));
            }

            List<DeliveryNoteDetailDO> deliveryNoteDetailDOList = deliveryNoteDetailMapper.listByDeliveryNoteIds(deliveryNoteIds);
            Map<String, List<DeliveryNoteDetailDO>> detailDOMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(deliveryNoteDetailDOList)) {
                detailDOMap = deliveryNoteDetailDOList.stream().collect(Collectors.groupingBy(DeliveryNoteDetailDO::getMaterialsNo));
            }

            //装箱详情
            List<BoxupDetailDO> materialsList = boxupDetailMapper.listByBoxupNos(boxupNos, deliveryNoteIds);

            Map<String, List<BoxupDetailDO>> boxupDetailMap = new HashMap<>();
            Map<String, PubMaterialsDO> pubMaterialsDOMap = new HashMap<>();
            List<String> materialsNos = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(materialsList)) {
                boxupDetailMap = materialsList.stream().collect(Collectors.groupingBy(BoxupDetailDO::getBoxupNo));
                materialsNos = materialsList.stream().map(BoxupDetailDO::getMaterialsNo).distinct().collect(Collectors.toList());
                List<PubMaterialsDO> pubMaterialsDOList = pubMaterialsMapper.selectByMaterialsNos(materialsNos);
                if (CollectionUtils.isNotEmpty(pubMaterialsDOList)) {
                    pubMaterialsDOMap = pubMaterialsDOList.stream().collect(Collectors.toMap(PubMaterialsDO::getMaterialsNo, Function.identity(), (k1, k2) -> k2));
                }
            }

            for (int i = 0; i < boxupNos.size(); i++) {
                List<BoxupMainDO> mainDOS = mainDOMap.get(boxupNos.get(i));
                BoxupMainDO mainDO = mainDOS.get(0);
                List<String> receiptBillNos = mainDOS.stream().map(BoxupMainDO::getDeliveryReceiptNo).distinct().collect(Collectors.toList());
                String billNo = StringUtils.join(receiptBillNos, ",");
                String checkerName = "";

                for (String receiptBillNo : receiptBillNos) {
                    if (receiptDOMap.containsKey(receiptBillNo)) {
                        DeliveryReceiptDO receiptDO = receiptDOMap.get(receiptBillNo);
                        if (StringUtils.isNotEmpty(receiptDO.getCheckerName())) {
                            checkerName = receiptDO.getCheckerName();
                            break;
                        }
                    }
                }

                printDeliveryReceiptVO = new PrintDeliveryReceiptVO();
                BeanUtils.copyProperties(mainDO, printDeliveryReceiptVO);
                printDeliveryReceiptVO.setBillNo(billNo);//交接单号
                printDeliveryReceiptVO.setCheckerName(checkerName);//验箱人
                // TODO: 2021/1/21 箱号按照装箱顺序
                printDeliveryReceiptVO.setBoxNo(i + 1);//箱号
                if (boxupDetailMap.containsKey(mainDO.getBoxupNo())) {
                    List<PrintDeliveryReceiptDetailVO> detailVOList = Lists.newArrayList();
                    List<BoxupDetailDO> boxupDetailDOList = boxupDetailMap.get(mainDO.getBoxupNo());

                    PrintDeliveryReceiptDetailVO printDeliveryReceiptDetailVO;
                    for (BoxupDetailDO boxupDetailDO : boxupDetailDOList) {
                        String materialsNo = boxupDetailDO.getMaterialsNo();
                        printDeliveryReceiptDetailVO = new PrintDeliveryReceiptDetailVO();
                        BeanUtils.copyProperties(boxupDetailDO, printDeliveryReceiptDetailVO);
                        if (billNo.startsWith("XGJK")) {//进出口运单
                            BarcodeManageDO barcodeDO = barcodeManageMapper.item(boxupDetailDO.getBarcode(), mainDO.getOrgId());
                            if (StringUtils.isEmpty(barcodeDO.getPurchaseContractNo())) {
                                throw new Exception("零件【" + materialsNo + "】--条码【" + boxupDetailDO.getBarcode() + "】对应批次号（采购订单号）不能为空");
                            }
                            printDeliveryReceiptDetailVO.setPurchaseContractNo(barcodeDO.getPurchaseContractNo());//采购合同编号
                            printDeliveryReceiptDetailVO.setMachineModel(barcodeDO.getMachineModel());//机型
                            if (StringUtils.isEmpty(printDeliveryReceiptVO.getCountry())) {
                                printDeliveryReceiptVO.setCountry(barcodeDO.getCountry());//国家
                            }

                            if (detailDOMap.containsKey(materialsNo)) {
                                Optional<DeliveryNoteDetailDO> noteDetailDOOptional = detailDOMap.get(materialsNo).stream().filter(item -> StringUtils.isNotBlank(item.getOriginalMaterialsNo())).findFirst();
                                if (noteDetailDOOptional.isPresent()) {
                                    printDeliveryReceiptDetailVO.setOriginalMaterialsNo(noteDetailDOOptional.get().getOriginalMaterialsNo());
                                }
                            }

                        } else {//进出口发运交接单
                            if (deliveryNoteDOMap.containsKey(boxupDetailDO.getDeliveryNoteId())) {
                                DeliveryNoteDO deliveryNoteDO = deliveryNoteDOMap.get(boxupDetailDO.getDeliveryNoteId());
                                if (StringUtils.isEmpty(deliveryNoteDO.getPurchaseContractNo())) {
                                    throw new Exception("零件【" + materialsNo + "】对应批次号（采购订单号）不能为空");
                                }

                                printDeliveryReceiptDetailVO.setPurchaseContractNo(deliveryNoteDO.getPurchaseContractNo());//采购合同编号
                                if (StringUtils.isEmpty(printDeliveryReceiptVO.getCountry())) {
                                    printDeliveryReceiptVO.setCountry(deliveryNoteDO.getCountry());//国家
                                }

                                //机型 原零件号
                                if (detailDOMap.containsKey(materialsNo)) {
                                    printDeliveryReceiptDetailVO.setMachineModel(detailDOMap.get(materialsNo).get(0).getMachineModel());
                                    Optional<DeliveryNoteDetailDO> noteDetailDOOptional = detailDOMap.get(materialsNo).stream().filter(item -> StringUtils.isNotBlank(item.getOriginalMaterialsNo())).findFirst();
                                    if (noteDetailDOOptional.isPresent()) {
                                        printDeliveryReceiptDetailVO.setOriginalMaterialsNo(noteDetailDOOptional.get().getOriginalMaterialsNo());
                                    }
                                }
                            }
                        }

                        printDeliveryReceiptDetailVO.setMaterialsDesCN(boxupDetailDO.getMaterialsDes());
                        //英文描述
                        if (pubMaterialsDOMap.containsKey(materialsNo)) {
                            printDeliveryReceiptDetailVO.setMaterialsDesEN(pubMaterialsDOMap.get(materialsNo).getMaterialsDesEn());
                        }
                        detailVOList.add(printDeliveryReceiptDetailVO);
                    }

                    //合并相同采购合同号，零件号
                    Map<String, Map<String, List<PrintDeliveryReceiptDetailVO>>> groupMap = detailVOList.stream().collect(
                            Collectors.groupingBy(PrintDeliveryReceiptDetailVO::getPurchaseContractNo,
                                    Collectors.groupingBy(PrintDeliveryReceiptDetailVO::getMaterialsNo)));

                    List<PrintDeliveryReceiptDetailVO> materialsNOList = Lists.newArrayList();
                    for (Map.Entry<String, Map<String, List<PrintDeliveryReceiptDetailVO>>> groupEntry : groupMap.entrySet()) {
                        for (Map.Entry<String, List<PrintDeliveryReceiptDetailVO>> entry : groupEntry.getValue().entrySet()) {
                            printDeliveryReceiptDetailVO = new PrintDeliveryReceiptDetailVO();
                            printDeliveryReceiptDetailVO.setPurchaseContractNo(groupEntry.getKey());

                            printDeliveryReceiptDetailVO.setMaterialsNo(entry.getKey());
                            List<PrintDeliveryReceiptDetailVO> deliveryReceiptDetailVOS = entry.getValue();
                            BigDecimal totalAmount = deliveryReceiptDetailVOS.stream().map(PrintDeliveryReceiptDetailVO::getQty)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            printDeliveryReceiptDetailVO.setQty(totalAmount);
                            printDeliveryReceiptDetailVO.setMaterialsDesEN(deliveryReceiptDetailVOS.get(0).getMaterialsDesEN());
                            printDeliveryReceiptDetailVO.setMaterialsDesCN(deliveryReceiptDetailVOS.get(0).getMaterialsDesCN());
                            printDeliveryReceiptDetailVO.setMachineModel(deliveryReceiptDetailVOS.get(0).getMachineModel());
                            printDeliveryReceiptDetailVO.setOriginalMaterialsNo(deliveryReceiptDetailVOS.get(0).getOriginalMaterialsNo());
                            materialsNOList.add(printDeliveryReceiptDetailVO);
                        }
                    }

                    printDeliveryReceiptVO.setMaterialsList(materialsNOList);
                }
                receiptVOList.add(printDeliveryReceiptVO);
            }
        }

        return receiptVOList;
    }


    /**
     * 同步装箱信息
     *
     * @param billNo 进出口单号
     */
    public ErrorCode syncPackInfo(String billNo, String billId, String orgId, String userId, String userName) {
        //根据进出口单号获取关联的发运交接单所有的装箱信息
        List<DeliveryReceiptDetailDO> deliveryReceiptDetailDOS = deliveryReceiptDetailMapper.listPackInfoByJckBillNo(billNo);
        //更新装箱信息中的交接单ID和编号
        if (deliveryReceiptDetailDOS != null) {

            //同步装箱信息
            syncBoxUp(deliveryReceiptDetailDOS, billNo, billId, orgId, userId, userName);

            deliveryReceiptDetailDOS.forEach(item -> {
                item.setDeliveryReceiptId(billId);
                item.setDeliveryReceiptNo(billNo);
            });
            for (DeliveryReceiptDetailDO deliveryReceiptDetailDO : deliveryReceiptDetailDOS) {
                //将装箱信息同步到进出口运单下面，如果装箱信息已存在则忽略
                deliveryReceiptDetailMapper.syncPackInfo(deliveryReceiptDetailDO);
            }
            return ErrorCode.Success;
        } else {
            return ErrorCode.SyncPackInfoError;
        }
    }

    /**
     * 同步装箱清单信息
     *
     * @param deliveryReceiptDetailDOS 进出口运单关联的发运交接单列表
     * @param billNo                   进出口单编号
     * @param billId                   进出口单ID
     * @return 同步结果
     */
    public ErrorCode syncBoxUp(List<DeliveryReceiptDetailDO> deliveryReceiptDetailDOS, String billNo,
                               String billId, String orgId, String userId, String userName) {

        //同步装箱信息
        for (DeliveryReceiptDetailDO deliveryReceiptDetailDO : deliveryReceiptDetailDOS) {
            BoxupMainVO mainVO = new BoxupMainVO();
            mainVO.setDeliveryReceiptId(deliveryReceiptDetailDO.getDeliveryReceiptId());
            mainVO.setDeliveryReceiptNo(deliveryReceiptDetailDO.getDeliveryReceiptNo());
            List<BoxupMainDO> mainDOS = boxupMainMapper.list(mainVO);

            for (BoxupMainDO mainDO : mainDOS) {
                //同步装箱主表信息
                //保存原始id，用于获取原装箱明细
                String oldBoxUpId = mainDO.getBoxupId();
                String newBoxUpId = "";
                //运单ID和运单编号
                mainDO.setDeliveryReceiptId(billId);
                mainDO.setDeliveryReceiptNo(billNo);
                mainDO.setCreateId(userId);
                mainDO.setCreateName(userName);
                mainDO.setCreateTime(new Date());
                //查询是否已存在
                BoxupMainVO param = new BoxupMainVO();
                param.setBoxupNo(mainDO.getBoxupNo());
                param.setDeliveryReceiptId(mainDO.getDeliveryReceiptId());
                param.setOrgId(orgId);
                //查询待更新数据是否已同步
                BoxupMainDO boxupMainDO = boxupMainMapper.getOne(param);
                //如果为空则新增
                if (boxupMainDO == null) {
                    ActionResult<String> id = fastGenClient.textGuid();
                    if (id == null || id.getCode() != 0) {
                        return ErrorCode.Failure;
                    }
                    newBoxUpId = id.getValue();
                    mainDO.setBoxupId(id.getValue());
                    mainDO.setOrgId(orgId);
                    //mainDO.setBoxCode(mainDO.getBoxCode());
                    boxupMainMapper.insert(mainDO);
                }
                //不为空则更新
                else {
                    newBoxUpId = boxupMainDO.getBoxupId();
                    mainDO.setBoxupId(boxupMainDO.getBoxupId());
                    mainDO.setOrgId(orgId);
                    //mainDO.setBoxCode(boxupMainDO.getBoxCode());
                    mainDO.setDeliveryStatus(null);
                    boxupMainMapper.update(mainDO);
                }

                //同步装箱明细信息
                List<BoxupDetailDO> boxupDetailDOS = boxupDetailMapper.detailList(oldBoxUpId);
                if (boxupDetailDOS == null) {
                    continue;
                }
                //保存发货通知单号和发货通知ID的对应关系
                Map<String, String> deliveryNoteMap = new HashMap<>();
                //查询进出口运单对应的发货通知单
                List<DeliveryReceiptLinkDO> deliveryReceiptLinkDOS = deliveryReceiptLinkMapper.list(billId);
                if (deliveryReceiptLinkDOS != null) {
                    deliveryReceiptLinkDOS.forEach(item -> {
                        deliveryNoteMap.put(item.getDeliveryNoteNo(), item.getDeliveryNoteId());
                    });
                }
                //查找发货通知单对应的条码信息
                BoxupMaterialsQuery boxupMaterialsQuery = new BoxupMaterialsQuery();
                boxupMaterialsQuery.setDeliveryReceiptLinkDOList(deliveryReceiptLinkDOS);
                List<WarehouseDeliveryRecordDO> warehouseDeliveryRecordDOS = warehouseDeliveryRecordMapper.listByBusinessOrder(boxupMaterialsQuery);

                List<BoxupDetailDO> processDetailDO = new ArrayList<>();
                //对条码和零件相同的装箱明细进行合并操作
                boxupDetailDOS.forEach(item -> {
                    //查找相同条码和零件编码的数据是否保存到集合中
                    Optional<BoxupDetailDO> boxupDetailDOOptional = processDetailDO.stream()
                            .filter(subItem -> StringUtils.equals(subItem.getBarcode(), item.getBarcode())
                                    && StringUtils.equals(subItem.getMaterialsNo(), item.getMaterialsNo())).findFirst();
                    //如果存在则获取原有数据并对数量进行求和
                    if (boxupDetailDOOptional.isPresent()) {
                        BoxupDetailDO boxupDetailDO = boxupDetailDOOptional.get();
                        if (item.getQty() != null && boxupDetailDO.getQty() != null) {
                            boxupDetailDO.setQty(boxupDetailDO.getQty().add(item.getQty()));
                        }
                    }
                    //如果不存在，则新增
                    else {
                        processDetailDO.add(item);
                    }
                });

                for (BoxupDetailDO boxupDetailDO : processDetailDO) {
                    boxupDetailDO.setBoxupId(newBoxUpId);
                    boxupDetailDO.setCreateId(userId);
                    boxupDetailDO.setCreateName(userName);
                    boxupDetailDO.setCreateTime(new Date());
                    //根据条码查找对应的发货通知单
                    if (warehouseDeliveryRecordDOS != null) {
                        Optional<WarehouseDeliveryRecordDO> deliveryRecordDOOptional = warehouseDeliveryRecordDOS.stream()
                                .filter(item -> StringUtils.equals(item.getBarCode(), boxupDetailDO.getBarcode()))
                                .findFirst();
                        if (deliveryRecordDOOptional.isPresent()) {
                            WarehouseDeliveryRecordDO filterData = deliveryRecordDOOptional.get();
                            //获取发货通知单号
                            String deliveryNoteNo = filterData.getBusinessOrder();
                            //根据通知单号获取发货通知单ID
                            String deliveryNoteId = deliveryNoteMap.get(deliveryNoteNo);
                            boxupDetailDO.setDeliveryNoteId(deliveryNoteId);
                            boxupDetailDO.setDeliveryNoteNo(deliveryNoteNo);
                        }
                    }
                    //查询待更新数据是否已同步
                    BoxupDetailDO oldDetailDO = boxupDetailMapper.itemByBarcodeAndId(boxupDetailDO.getBarcode(), boxupDetailDO.getBoxupId());
                    //不存在则执行新增操作
                    if (oldDetailDO == null) {
                        boxupDetailMapper.insert(boxupDetailDO);
                    }
                    //存在执行更新操作
                    else {
                        boxupDetailMapper.update(boxupDetailDO);
                    }

                }

            }
        }

        return ErrorCode.Success;
    }

    public PageCommonVO list4JckDomestic(SearchCommonVO<DeliveryReceiptQueryParam> condition, String orgId, String deptId, String userId) throws Exception {
        PageCommonVO pageCommonVO = new PageCommonVO();
        //获取仓库配置权限
        WareHousePermission wareHousePermission = relationService.hasMajorWareHousePermission(orgId, deptId);

        UserDetailDTO userInfo = authClient.getUserDetail(userId).getValue();
        //当前用户是服务人员
        if (StringUtil.isNotEmpty(userInfo.getIsService()) && "1".equals(userInfo.getIsService())) {
            condition.getFilters().setServiceName(userInfo.getName());
        } else if (!wareHousePermission.isHasPermission()) {
            pageCommonVO.setPageInfo(new PageInfo(new ArrayList()));
            pageCommonVO.setPageInfoList(new ArrayList<>());
            return pageCommonVO;
        } else {
            condition.getFilters().setWarehousePermitList(wareHousePermission.getPermissionWarehouses());
        }

        PageHelperPlus.orderBy("create_date desc");
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        condition.getFilters().setBillNosList(xcmg.device.infra.StringUtil.splitList(condition.getFilters().getBillNos()));
        List<DeliveryReceiptDO> doList = deliveryReceiptMapper.list4JckDomestic(condition.getFilters());
        List<DeliveryReceiptVO> voList = new ArrayList<>();
        for (DeliveryReceiptDO deliveryReceiptDO : doList
        ) {
            DeliveryReceiptVO deliveryReceiptVO = new DeliveryReceiptVO();
            BeanUtils.copyProperties(deliveryReceiptDO, deliveryReceiptVO);
            int recordCount = deliveryReceiptLogisticsMapper.countByDate(deliveryReceiptDO.getBillNo(), org.apache.commons.lang3.time.DateFormatUtils.format(new Date(), "yyyyMMdd"));
            deliveryReceiptVO.setRecordFlag(recordCount > 0 ? DeliveryReceiptVO.RECORD_FLAG_YES : DeliveryReceiptVO.RECORD_FLAG_NO);
            deliveryReceiptVO.setPurchaseLevel(getPurchaseLevel(deliveryReceiptDO.getId()));
            voList.add(deliveryReceiptVO);
        }
        pageCommonVO.setPageInfo(new PageInfo(doList));
        pageCommonVO.setPageInfoList(voList);
        return pageCommonVO;
    }

    public PageCommonVO list4JckOverseas(SearchCommonVO<DeliveryReceiptQueryParam> condition, String orgId, String deptId, String userId) throws Exception {
        PageCommonVO pageCommonVO = new PageCommonVO();
        //获取仓库配置权限
        WareHousePermission wareHousePermission = relationService.hasMajorWareHousePermission(orgId, deptId);

        UserDetailDTO userInfo = authClient.getUserDetail(userId).getValue();
        //当前用户是服务人员
        if (StringUtil.isNotEmpty(userInfo.getIsService()) && "1".equals(userInfo.getIsService())) {
            condition.getFilters().setServiceName(userInfo.getName());
        } else if (!wareHousePermission.isHasPermission()) {
            pageCommonVO.setPageInfo(new PageInfo(new ArrayList()));
            pageCommonVO.setPageInfoList(new ArrayList<>());
            return pageCommonVO;
        } else {
            condition.getFilters().setWarehousePermitList(wareHousePermission.getPermissionWarehouses());
        }

        PageHelperPlus.orderBy("create_date desc");
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        condition.getFilters().setBillNosList(xcmg.device.infra.StringUtil.splitList(condition.getFilters().getBillNos()));
        List<DeliveryReceiptDO> doList = deliveryReceiptMapper.list4JckOverseas(condition.getFilters());
        List<DeliveryReceiptVO> voList = new ArrayList<>();
        for (DeliveryReceiptDO deliveryReceiptDO : doList
        ) {
            DeliveryReceiptVO deliveryReceiptVO = new DeliveryReceiptVO();
            BeanUtils.copyProperties(deliveryReceiptDO, deliveryReceiptVO);
            int recordCount = deliveryReceiptLogisticsMapper.countByDate(deliveryReceiptDO.getBillNo(), org.apache.commons.lang3.time.DateFormatUtils.format(new Date(), "yyyyMMdd"));
            deliveryReceiptVO.setRecordFlag(recordCount > 0 ? DeliveryReceiptVO.RECORD_FLAG_YES : DeliveryReceiptVO.RECORD_FLAG_NO);
            deliveryReceiptVO.setPurchaseLevel(getPurchaseLevel(deliveryReceiptDO.getId()));
            voList.add(deliveryReceiptVO);
        }
        pageCommonVO.setPageInfo(new PageInfo(doList));
        pageCommonVO.setPageInfoList(voList);
        return pageCommonVO;
    }

    @Transactional(rollbackFor = Exception.class)
    public ActionResult autoAdd(AutoDeliveryReceiptVO autoDeliveryReceiptVO, String userId, String orgId) throws Exception {

        log.info("**********自动新增进出口运单开始*********************");
        String username = commonService.getUserName(userId);
        String billNo = autoDeliveryReceiptVO.getBillNo();
        String warehouseCode = autoDeliveryReceiptVO.getWarehouseCode();
        String locationCode = autoDeliveryReceiptVO.getLocationCode();//库存储位

        //查询发运交接单
        DeliveryReceiptDO deliveryReceiptDO = deliveryReceiptMapper.itemByNo(billNo);
        if (StringUtils.isNotEmpty(deliveryReceiptDO.getJckBillNo())) {
            throw new Exception("发运交接单零件已添加到进出口运单中,请重新选择");
        }
        if (StringUtils.isEmpty(deliveryReceiptDO.getCountry())) {
            throw new Exception("发运交接单国家不能为空");
        }
        String billId = deliveryReceiptDO.getId();

        //查询交接单零件详情
        List<DeliveryReceiptMaterialVO> materialVOList = deliveryReceiptMaterialService.list(billId, orgId);
        //交接单零件详情map
        Map<String, DeliveryReceiptMaterialVO> materialVOMap = materialVOList.stream()
                .collect(Collectors.toMap(DeliveryReceiptMaterialVO::getMaterialsNo, Function.identity(), (k1, k2) -> k2));

        SaleIntentionVO saleIntentionVO = new SaleIntentionVO();
        List<SaleIntentionDetailVO> intentionDetailVOList = new ArrayList<>();
        if (StringUtils.isNotEmpty(autoDeliveryReceiptVO.getSaleNo())) {//选择销售单
            String saleNo = autoDeliveryReceiptVO.getSaleNo();

            //校验国家是否相同
            if (!deliveryReceiptDO.getCountry().equals(autoDeliveryReceiptVO.getCountry())) {
                throw new Exception("发运交接单中国家与销售订单中国家不统一");
            }

            //查询销售订单及详情
            String saleId = saleIntentionMapper.selectIdByNo(saleNo);
            SaleAddVO saleAddVO = saleIntentionService.itemByDeliveryNote(saleId);

            saleIntentionVO = saleAddVO.getHeaderInfo();
            intentionDetailVOList = saleAddVO.getMaterialList();
            Map<String, SaleIntentionDetailVO> intentionMaterialsMap = intentionDetailVOList.stream()
                    .collect(Collectors.toMap(SaleIntentionDetailVO::getMaterialsNo, Function.identity(), (k1, k2) -> k2));

            //校验发运交接单中零件数量是否与销售订单数量匹配
            if (materialVOList.size() <= saleAddVO.getMaterialList().size()) {
                for (DeliveryReceiptMaterialVO receiptMaterialVO : materialVOList) {
                    if (intentionMaterialsMap.containsKey(receiptMaterialVO.getMaterialsNo())) {
                        SaleIntentionDetailVO intentionDetailVO = intentionMaterialsMap.get(receiptMaterialVO.getMaterialsNo());
                        if (receiptMaterialVO.getQty().add(intentionDetailVO.getInformedAmount())
                                .compareTo(intentionDetailVO.getAmountAfterAdjust()) == 1) {
                            throw new Exception("发运交接单中零件【" + receiptMaterialVO.getMaterialsNo() + "】数量不能大于销售订单中剩余发货数量,请重新选择");
                        }
                    } else {
                        throw new Exception("销售订单中不包含发运交接单中零件【" + receiptMaterialVO.getMaterialsNo() + "】,请重新选择");
                    }
                }
            } else {
                throw new Exception("发运交接单零件与销售订单零件总数不匹配");
            }
        } else {//未选择，新建销售单
            if (StringUtils.isEmpty(autoDeliveryReceiptVO.getDealerOrgId())
                    || StringUtils.isEmpty(autoDeliveryReceiptVO.getDealerOrgName())) {
                throw new Exception("客户不能为空");
            }
            if (StringUtils.isEmpty(autoDeliveryReceiptVO.getCountry())) {
                throw new Exception("国家不能为空");
            }
            if (StringUtils.isEmpty(autoDeliveryReceiptVO.getCreateId())
                    || StringUtils.isEmpty(autoDeliveryReceiptVO.getCreateName())) {
                throw new Exception("业务员不能为空");
            }

            //------------------------创建销售单---------------------------------
            SaleAddVO saleAddVO = new SaleAddVO();
            saleIntentionVO.setStatus(String.valueOf(SaleStatus.Submit.getCode()));
            saleIntentionVO.setSupplierOrgId(orgId);
            saleIntentionVO.setCreatorId(autoDeliveryReceiptVO.getCreateId());//业务员
            saleIntentionVO.setCreateName(autoDeliveryReceiptVO.getCreateName());
            saleIntentionVO.setCreateType(1);//手动
            saleIntentionVO.setPurchaseOrgId(autoDeliveryReceiptVO.getDealerOrgId());//客户
            saleIntentionVO.setPurchaseOrgName(autoDeliveryReceiptVO.getDealerOrgName());
            saleIntentionVO.setCountry(autoDeliveryReceiptVO.getCountry());//国家
            saleIntentionVO.setDeliverTypeId(autoDeliveryReceiptVO.getShippingMethodId());
            saleIntentionVO.setDeliverTypeName(autoDeliveryReceiptVO.getShippingMethod());
            saleIntentionVO.setIsLimit(0);
            saleIntentionVO.setIsDirect(0);

            saleAddVO.setHeaderInfo(saleIntentionVO);

            //销售单详情
            SaleIntentionDetailVO saleIntentionDetailVO;
            for (DeliveryReceiptMaterialVO materVO : materialVOList) {
                saleIntentionDetailVO = new SaleIntentionDetailVO();
                BeanUtils.copyProperties(materVO, saleIntentionDetailVO);
                saleIntentionDetailVO.setAmountAfterAdjust(materVO.getQty());
                saleIntentionDetailVO.setInformedAmount(BigDecimal.ZERO);//已发货数量
                intentionDetailVOList.add(saleIntentionDetailVO);
            }
            saleAddVO.setMaterialList(intentionDetailVOList);

            ErrorCode saleCode = saleIntentionService.add(saleAddVO);
            if (saleCode.getCode() != ErrorCode.Success.getCode()) {
                throw new Exception("创建销售订单失败--" + saleCode.getDesc());
            }

        }

        //------------------------入库---------------------------------
        //1、创建运单入库单
        //判断是否创建入库单
        //查询入库单号
        ReceiptInVO receiptInVO = new ReceiptInVO();
        receiptInVO.setReceiptNo(billNo);
        List<ReceiptInDO> receiptInList = receiptInMapper.list(receiptInVO);
        if (CollectionUtils.isEmpty(receiptInList)) {//未创建
            ReceiptInAddVO receiptInAddVO = new ReceiptInAddVO();
            ReceiptInVO headerInfo = new ReceiptInVO();
            headerInfo.setWarehouseCode(warehouseCode);
            headerInfo.setReceiptId(billId);
            headerInfo.setReceiptNo(billNo);
            headerInfo.setCreateId(userId);
            headerInfo.setSupplierOrgId(deliveryReceiptDO.getOrgId());
            headerInfo.setOrgId(orgId);
            receiptInAddVO.setHeaderInfo(headerInfo);

            List<ReceiptInDetailVO> detailList = new ArrayList<>();
            ReceiptInDetailVO detailVO;
            for (DeliveryReceiptMaterialVO materialVO : materialVOList) {
                detailVO = new ReceiptInDetailVO();
                BeanUtils.copyProperties(materialVO, detailVO);
                detailVO.setAmount(materialVO.getQty());
                detailList.add(detailVO);
            }

            receiptInAddVO.setDetailList(detailList);

            ErrorCode errorCode = receiptInService.add(receiptInAddVO, userId, orgId);
            if (errorCode.getCode() != ErrorCode.Success.getCode()) {
                throw new Exception("创建运单入库单失败");
            }
            receiptInList = receiptInMapper.list(receiptInVO);
        }

        //查询入库单号
        ReceiptInDO receiptInDO = receiptInList.get(0);
        String receiptInNo = receiptInDO.getBillNo();
        String receiptInId = receiptInDO.getId();

        //判断入库单是否已入库 0 未入库 1 已入库
        if (receiptInDO.getStatus() == 0 || receiptInDO.getStatus() == 1) {
            List<ReceiptInDetailDO> listDO = receiptInDetailMapper.listByMainId(receiptInId);
            //过滤未入库
            List<String> materialsNos = listDO.stream().filter(receiptInDetailDO -> receiptInDetailDO.getStatus() != 2)
                    .map(ReceiptInDetailDO::getMaterialsNo).distinct().collect(Collectors.toList());

            //2、运单条码自动入库
            //自动入库--支持部分入库
            if (StringUtils.isEmpty(warehouseCode)) {
                throw new Exception("调入仓库不能为空");
            }

            WarehouseDO warehouse = warehouseDOMapper.itemByWarehouseCode(orgId, warehouseCode);
            if (null == warehouse || null == warehouse.getIsBarCode()) {
                throw new Exception("调入仓库是否条码仓不能为空");
            }

            if (warehouse.getIsBarCode() == 1) {//条码化
                //根据运单id查询关联发货通知单号
                List<String> deliveryNoteNoList = deliveryReceiptLinkMapper.findByDeliveryBillNo(billNo);
                if (CollectionUtils.isNotEmpty(deliveryNoteNoList)) {
                    WarehouseDeliveryRecordVO recordVO = new WarehouseDeliveryRecordVO();
                    recordVO.setBusinessOrderList(deliveryNoteNoList);
                    List<WarehouseDeliveryRecordDO> recordDOList = warehouseDeliveryRecordMapper.list(recordVO);
                    if (!CollectionUtils.isEmpty(recordDOList)) {

                        // TODO: 2021/4/9 回写状态时根据发运交接单数量判断--（数量匹配上就入库修改状态-不精确）
                        //查询入库记录判断是否部分入库
                        Map<String, WarehouseDeliveryRecordDO> deliveryRecordDOMap = recordDOList.stream().collect(Collectors.toMap
                                (WarehouseDeliveryRecordDO::getBarCode, Function.identity(), (k1, k2) -> {
                                    k1.setAmount(k1.getAmount().add(k2.getAmount()));
                                    return k1;
                                }));
                        List<String> barcodeList = recordDOList.stream().map(WarehouseDeliveryRecordDO::getBarCode).distinct().collect(Collectors.toList());
                        if (CollectionUtils.isNotEmpty(barcodeList)) {
                            WarehouseInboundRecordAddVO warehouseInboundRecordVO;
                            for (String barcode : barcodeList) {
                                String materialNo = deliveryRecordDOMap.get(barcode).getMaterialNo();
                                if (materialsNos.contains(materialNo)) {
                                    //校验条码
                                    BarcodeManageDO barcodeDO = barcodeManageMapper.item(barcode, orgId);
                                    if (barcodeDO != null && barcodeDO.getBarcodeFlag() == 1 && "3".equals(barcodeDO.getBarcodeStatus())) {
                                        throw new Exception("条码【" + barcode + "】已拆分!");
                                    }
                                    //拆分新增条码
                                    warehouseInventoryService.findByBarCodeForInbound(barcode, receiptInNo, userId, orgId);

                                    //条码入库
                                    warehouseInboundRecordVO = new WarehouseInboundRecordAddVO();
                                    warehouseInboundRecordVO.setBarCode(barcode);
                                    warehouseInboundRecordVO.setBusinessOrder(receiptInNo);
                                    warehouseInboundRecordVO.setFrozen(0);
                                    warehouseInboundRecordVO.setAmount(deliveryRecordDOMap.get(barcode).getAmount());

                                    warehouseInboundRecordVO.setLocationCode(locationCode);
                                    ErrorCode errorCode1 = warehouseInboundRecordService.add(warehouseInboundRecordVO, userId, orgId);
                                    if (errorCode1.getCode() != ErrorCode.Success.getCode()) {
                                        throw new Exception("条码【" + barcode + "】入库失败--" + errorCode1.getDesc());
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        //------------------------出库---------------------------------
        //3、生成发货通知单
        DeliveryNoteAddVO deliveryNoteAddVO = new DeliveryNoteAddVO();
        DeliveryNoteVO deliveryNoteVO = new DeliveryNoteVO();
        BeanUtils.copyProperties(saleIntentionVO, deliveryNoteVO);
        deliveryNoteVO.setId(null);
        deliveryNoteVO.setDeliveryTypeId(saleIntentionVO.getDeliverTypeId());//发货方式
        deliveryNoteVO.setDeliveryTypeName(saleIntentionVO.getDeliverTypeName());//发货方式名称
        deliveryNoteVO.setAddress(saleIntentionVO.getReceiveAddress());//收货地址
        deliveryNoteVO.setOutLocation(warehouseCode);//仓库
        deliveryNoteVO.setOutArea(autoDeliveryReceiptVO.getAreaCode());//库区
        deliveryNoteAddVO.setHeaderInfo(deliveryNoteVO);

        List<DeliveryNoteDetailVO> deliveryNoteDetailVOS = new ArrayList<>();
        DeliveryNoteDetailVO deliveryNoteDetailVO;
        //遍历销售订单详情
        Iterator<SaleIntentionDetailVO> iterator = intentionDetailVOList.iterator();
        while (iterator.hasNext()) {
            SaleIntentionDetailVO intentionDetailVO = iterator.next();
            if (materialVOMap.containsKey(intentionDetailVO.getMaterialsNo())) {
                deliveryNoteDetailVO = new DeliveryNoteDetailVO();
                BeanUtils.copyProperties(intentionDetailVO, deliveryNoteDetailVO);
                deliveryNoteDetailVO.setDeliveryQty(materialVOMap.get(deliveryNoteDetailVO.getMaterialsNo()).getQty());//本次发货数量
                deliveryNoteDetailVO.setSendQty(intentionDetailVO.getInformedAmount());//已发货数量
                deliveryNoteDetailVOS.add(deliveryNoteDetailVO);
            } else {
                iterator.remove();
            }
        }
        if (CollectionUtils.isEmpty(deliveryNoteDetailVOS)) {
            throw new Exception("生成发货通知单失败--通知单中零件不能为空");
        }

        deliveryNoteAddVO.setMaterialList(deliveryNoteDetailVOS);
        ErrorCode errorCode2 = deliveryNoteService.add(deliveryNoteAddVO, userId, orgId, false);
        if (errorCode2.getCode() != ErrorCode.Success.getCode()) {
            throw new Exception("生成发货通知单失败--" + errorCode2.getDesc());
        }

        //4、创建进出口运单
        //查询发货通知单及详情
        String deliveryNoteNo = deliveryNoteAddVO.getHeaderInfo().getDeliveryNo();
        String deliveryNoteId = deliveryNoteAddVO.getHeaderInfo().getId();

        String billType = "XGFT";
        if (StringUtils.isEmpty(autoDeliveryReceiptVO.getJckBillNo())) { //新增
            DeliveryReceiptDO jckDeliveryReceiptDO = new DeliveryReceiptDO();
            BeanUtils.copyProperties(deliveryReceiptDO, jckDeliveryReceiptDO);
            jckDeliveryReceiptDO.setCreateId(userId);
            jckDeliveryReceiptDO.setCreateName(username);
            jckDeliveryReceiptDO.setUpdateId(username);
            jckDeliveryReceiptDO.setCreateDate(new Date());
            jckDeliveryReceiptDO.setUpdateDate(new Date());
            jckDeliveryReceiptDO.setOutLocation(warehouseCode);//仓库
            jckDeliveryReceiptDO.setCountry(autoDeliveryReceiptVO.getCountry());
            jckDeliveryReceiptDO.setReceiverName(saleIntentionVO.getReceiverName());
            jckDeliveryReceiptDO.setReceiverTel(saleIntentionVO.getReceiverPhone());
            jckDeliveryReceiptDO.setReceiverAddress(saleIntentionVO.getReceiveAddress());
            jckDeliveryReceiptDO.setReceiverFax(saleIntentionVO.getReceiverFax());
            jckDeliveryReceiptDO.setSettlementId(saleIntentionVO.getSettleTypeId());
            jckDeliveryReceiptDO.setSettlementDesc(saleIntentionVO.getSettleTypeName());
            jckDeliveryReceiptDO.setDispatcherName(username);
            CompanyInfoVO companyInfoVO = companyInfoService.info(orgId);

            List<DeliveryReceiptLinkVO> linkVOList = new ArrayList<>();
            DeliveryReceiptLinkVO linkVO = new DeliveryReceiptLinkVO();
            linkVO.setBillType(billType);
            linkVO.setDeliveryNoteId(deliveryNoteId);
            linkVO.setDeliveryNoteNo(deliveryNoteNo);
            linkVO.setSaleBillNo(saleIntentionVO.getSaleNo());//销售单号
            linkVO.setPurchaseBillNo(saleIntentionVO.getPurchaseNo());//采购订单号
            linkVO.setStatus("2");//已出库
            linkVOList.add(linkVO);
            if (!isCanInsert(billType, linkVOList, companyInfoVO, null)) {
                throw new Exception(ErrorCode.AddressIsUnlikeness.getDesc());//地址未统一
            }
            String companyName = null == companyInfoVO ? "" : companyInfoVO.getCompanyName();
            jckDeliveryReceiptDO.setOrgId(orgId);
            jckDeliveryReceiptDO.setOrgName(companyName);

            //客户id+名称
            jckDeliveryReceiptDO.setDealerOrgId(saleIntentionVO.getPurchaseOrgId());
            jckDeliveryReceiptDO.setDealerOrgName(saleIntentionVO.getPurchaseOrgName());
            ActionResult<String> textResult = fastGenClient.textGuid();
            if (textResult.getCode() != ErrorCode.Success.getCode()) {
                throw new Exception("生成进出口运单号失败！");
            }
            String jckBillId = textResult.getValue();
            jckDeliveryReceiptDO.setId(jckBillId);
            jckDeliveryReceiptDO.setBillNo(genDocumentService.genDocumentNo(BillDesc.JCKDeliveryReceiptNo, orgId));
            jckDeliveryReceiptDO.setAuditStatus(DeliveryReceiptEnum.Status.AuditPass.toString());
            DataDictionaryDO auditDataDictionaryDO = dataDictionaryMapper.itemByCode(DeliveryReceiptEnum.Status.Name.toString(), DeliveryReceiptEnum.Status.AuditPass.toString());
            String auditDesc = "审核通过";
            if (auditDataDictionaryDO != null) {
                auditDesc = auditDataDictionaryDO.getName();
            }
            jckDeliveryReceiptDO.setAuditDesc(auditDesc);
            jckDeliveryReceiptDO.setIsDel(false);
            jckDeliveryReceiptDO.setDeliveryStatus(DeliveryReceiptEnum.DeliveryStatus.UnDelivery.toString());
            DataDictionaryDO deliveryDataDictionaryDO = dataDictionaryMapper.itemByCode(DeliveryReceiptEnum.DeliveryStatus.Name.toString(), DeliveryReceiptEnum.DeliveryStatus.UnDelivery.toString());
            String deliveryStatusDesc = "未发货";
            if (deliveryDataDictionaryDO != null) {
                deliveryStatusDesc = deliveryDataDictionaryDO.getName();
            }
            jckDeliveryReceiptDO.setDeliveryDesc(deliveryStatusDesc);
            jckDeliveryReceiptDO.setCommitType(0);
            jckDeliveryReceiptDO.setCommitId(null);
            jckDeliveryReceiptDO.setCommitTime(null);
            if (jckDeliveryReceiptDO.getSalesType() == "0") { //暂时先写死，做三包出库的时候根据三包方案修改
                jckDeliveryReceiptDO.setSalesTypeDesc("正常销售");
            } else {
                jckDeliveryReceiptDO.setSalesTypeDesc("三包");
            }

            // 发出仓库
            jckDeliveryReceiptDO.setOutLocation(getOutLocation(linkVO));

            List<String> statusList = linkVOList.stream().map(DeliveryReceiptLinkVO::getStatus).collect(Collectors.toList());

            //出库状态
            setOutStatus(jckDeliveryReceiptDO, statusList);

            //保存辅料费用更新关系
            jckDeliveryReceiptDO.setAccessoriesFee(autoDeliveryReceiptVO.getAccessoriesFee());

            //新增发运交接单
            if (deliveryReceiptMapper.insert(jckDeliveryReceiptDO) <= 0) {
                throw new Exception("创建进出口运单失败！");
            }

            //回写进出口运单号
            autoDeliveryReceiptVO.setJckBillNo(jckDeliveryReceiptDO.getBillNo());

            //新增交接单关联表
            List<String> outIds = new ArrayList<>();
            for (DeliveryReceiptLinkVO billVO : linkVOList) {
                DeliveryReceiptLinkDO deliveryReceiptLinkDO = new DeliveryReceiptLinkDO();
                BeanUtils.copyProperties(billVO, deliveryReceiptLinkDO);
                deliveryReceiptLinkDO.setDeliveryBillId(jckBillId);
                deliveryReceiptLinkDO.setDeliveryBillNo(jckDeliveryReceiptDO.getBillNo());
                if (deliveryReceiptLinkMapper.insert(deliveryReceiptLinkDO) <= 0) {
                    throw new Exception("生成进出口运单关联表失败");
                }
                outIds.add(deliveryReceiptLinkDO.getDeliveryNoteId());
                //更新三日计划交货状态
                updateThreeDayPlanDlvStatus(billVO.getbId(), 1);
            }
            //发运交接单零件
            deliveryReceiptMaterialService.add(outIds, jckDeliveryReceiptDO);

            //更新发运交接单与进出口运单关联信息
            if (deliveryReceiptMapper.updateJckBillNo(jckDeliveryReceiptDO.getBillNo(), billId) <= 0) {
                throw new Exception("更新发运交接单中进出口运单号失败");
            }

        } else {//更新增加零件
            DeliveryReceiptDO jckReceiptDO = deliveryReceiptMapper.itemByNo(autoDeliveryReceiptVO.getJckBillNo());

            if (StringUtils.isNotEmpty(jckReceiptDO.getDealerOrgId()) && StringUtils.isNotEmpty(autoDeliveryReceiptVO.getDealerOrgId())) {
                if (!jckReceiptDO.getDealerOrgId().equals(autoDeliveryReceiptVO.getDealerOrgId())) {
                    throw new Exception("选择客户与进出口运单中客户不统一");
                }
            }
            if (StringUtils.isNotEmpty(jckReceiptDO.getCountry()) && StringUtils.isNotEmpty(autoDeliveryReceiptVO.getCountry())) {
                if (!jckReceiptDO.getCountry().equals(autoDeliveryReceiptVO.getCountry())) {
                    throw new Exception("选择国家与进出口运单中国家不统一");
                }
            }
            if (StringUtils.isNotEmpty(jckReceiptDO.getCountry())) {
                if (!jckReceiptDO.getCountry().equals(deliveryReceiptDO.getCountry())) {
                    throw new Exception("发运交接单中国家与进出口运单中国家不统一");
                }
            }

            jckReceiptDO.setShippingMethod(autoDeliveryReceiptVO.getShippingMethod());
            jckReceiptDO.setShippingMethodId(autoDeliveryReceiptVO.getShippingMethodId());
            jckReceiptDO.setAccessoriesFee(autoDeliveryReceiptVO.getAccessoriesFee());
            deliveryReceiptMapper.update(jckReceiptDO);

            //查询已关联的发货通知单列表
            List<DeliveryReceiptLinkDO> linkVOList = deliveryReceiptLinkMapper.list(jckReceiptDO.getId());

            List<String> billNosList = linkVOList.stream().map(DeliveryReceiptLinkDO::getDeliveryNoteNo).collect(Collectors.toList());
            DeliveryNoteVO noteVO = new DeliveryNoteVO();
            noteVO.setBillNosList(billNosList);
            List<DeliveryNoteDO> deliveryNoteDOList = deliveryNoteMapper.list(noteVO);

            for (DeliveryNoteDO deliveryNoteDO : deliveryNoteDOList) {
                if (StringUtils.isEmpty(deliveryNoteDO.getCountry())) {
                    throw new Exception("进出口运单关联发货通知单【" + deliveryNoteDO.getDeliveryNo() + "】国家不能为空");
                }
                if (!deliveryNoteDO.getCountry().equals(deliveryNoteAddVO.getHeaderInfo().getCountry())) {
                    throw new Exception("发货通知单国家不统一");
                }
            }

            List<String> outIds = linkVOList.stream().map(DeliveryReceiptLinkDO::getDeliveryNoteId).collect(Collectors.toList());

            DeliveryReceiptLinkDO deliveryReceiptLinkDO = new DeliveryReceiptLinkDO();
            deliveryReceiptLinkDO.setBillType(billType);
            deliveryReceiptLinkDO.setDeliveryNoteId(deliveryNoteId);
            deliveryReceiptLinkDO.setDeliveryNoteNo(deliveryNoteNo);
            deliveryReceiptLinkDO.setSaleBillNo(saleIntentionVO.getSaleNo());
            deliveryReceiptLinkDO.setPurchaseBillNo(saleIntentionVO.getPurchaseNo());
            deliveryReceiptLinkDO.setDeliveryBillId(jckReceiptDO.getId());
            deliveryReceiptLinkDO.setDeliveryBillNo(jckReceiptDO.getBillNo());
            deliveryReceiptLinkDO.setStatus("2");//已出库
            if (deliveryReceiptLinkMapper.insert(deliveryReceiptLinkDO) <= 0) {
                throw new Exception("生成进出口运单关联表失败");
            }
            outIds.add(deliveryReceiptLinkDO.getDeliveryNoteId());
            //更新三日计划交货状态
            updateThreeDayPlanDlvStatus(deliveryReceiptLinkDO.getbId(), 1);

            //先删除之前累加的零件
            if (deliveryReceiptMaterialMapper.deleteByDeliveryReceiptId(jckReceiptDO.getId()) <= 0) {
                throw new Exception("删除进出口运单零件失败");
            }
            //删除出库事务表及出库事务详情表
            if (warehouseDeliveryMapper.deleteByBusinessOrder(jckReceiptDO.getBillNo()) <= 0) {
                throw new Exception("删除出库事务表数据失败");
            }
            if (warehouseDeliveryDetailMapper.deleteByBusinessOrder(jckReceiptDO.getBillNo()) <= 0) {
                throw new Exception("删除出库事务详情表数据失败");
            }

            //发运交接单零件
            deliveryReceiptMaterialService.add(outIds, jckReceiptDO);

            //更新发运交接单与进出口运单关联信息
            if (deliveryReceiptMapper.updateJckBillNo(jckReceiptDO.getBillNo(), billId) <= 0) {
                throw new Exception("更新发运交接单中进出口运单号失败");
            }

        }

        log.info("**********进出口运单创建成功***************************");

        //5、发货通知单自动出库
        // 遍历入库条码
        //根据发运交接单查询入库记录
        WarehouseInboundRecordVO recordVO = new WarehouseInboundRecordVO();
        recordVO.setBusinessOrder(receiptInNo);
        List<WarehouseInboundRecordDO> recordDOList = warehouseInboundRecordMapper.list(recordVO);
        WarehouseDeliveryRecordBatchAddVO batchAddVO;
        for (WarehouseInboundRecordDO recordDO : recordDOList) {
            batchAddVO = new WarehouseDeliveryRecordBatchAddVO();
            List<WarehouseDeliveryRecordAddVO> recordList = new ArrayList<>();

            WarehouseDeliveryRecordAddVO warehouseDeliveryRecordVO = new WarehouseDeliveryRecordAddVO();
            warehouseDeliveryRecordVO.setBarCode(recordDO.getBarCode());
            warehouseDeliveryRecordVO.setBusinessOrder(autoDeliveryReceiptVO.getJckBillNo());//发货通知单/发运交接单
            warehouseDeliveryRecordVO.setAmount(recordDO.getAmount());//出库数量
            warehouseDeliveryRecordVO.setSplitAmount(BigDecimal.ZERO);
            warehouseDeliveryRecordVO.setDeliveryReceiptNo(autoDeliveryReceiptVO.getJckBillNo());
            recordList.add(warehouseDeliveryRecordVO);
            batchAddVO.setRecordList(recordList);

            ErrorCode errorCode1 = warehouseDeliveryRecordService.batchAdd(batchAddVO, userId, orgId);
            ;
            if (errorCode1.getCode() != ErrorCode.Success.getCode()) {
                throw new Exception("发货通知单自动出库失败--" + errorCode1.getDesc());
            }
        }

        log.info("**********发货通知单自动出库成功*********************");

        log.info("**********自动新增进出口运单结束*********************");

        return ActionResultUtil.errorActionResult(ErrorCode.Success);
    }

    public DeliveryReceipt4AutoVO item4Auto(String billId) {

        DeliveryReceipt4AutoVO autoVO = new DeliveryReceipt4AutoVO();
        List<DeliveryReceiptMaterialDO> materialDOList = deliveryReceiptMaterialMapper.list(billId);
        if (CollectionUtils.isNotEmpty(materialDOList)) {
            List<DeliveryReceiptMaterialDO> sortMaterialList = materialDOList.stream().sorted(Comparator.comparing(DeliveryReceiptMaterialDO::getMaterialsNo)).collect(Collectors.toList());
            autoVO.setMaterialVOList(BeanUtil.do2bo4List(sortMaterialList, DeliveryReceiptMaterialVO.class));
        }

        //查询发运交接单关联销售订单
        String saleNo = "";
        List<DeliveryReceiptLinkDO> linkVOList = deliveryReceiptLinkMapper.list(billId);
        if (CollectionUtils.isNotEmpty(linkVOList)) {
            List<String> purchaseBillNosList = linkVOList.stream().map(DeliveryReceiptLinkDO::getPurchaseBillNo).distinct().collect(Collectors.toList());
            //查询采购单关联销售单
            PurchaseRequestDO requestDO = purchaseRequestMapper.itemByBillNo(purchaseBillNosList.get(0));
            if (null != requestDO) {
                saleNo = requestDO.getPurchaseContractNo();
            }
        }
        autoVO.setSaleNo(saleNo);
        return autoVO;
    }

//    /**
//     * @Desc 同步发货明细到NS
//     * @Author Mr.dong
//     * @Date 2021/4/1 14:35
//     */
//    @Transactional(rollbackFor = Exception.class)
//    public ErrorCode syncDelivery4NS(String billId) throws Exception {
//        DeliveryReceiptDO deliveryReceiptDO = deliveryReceiptMapper.item(billId);
//        if (deliveryReceiptDO == null) {
//            return ErrorCode.IllegalArument;
//        }
//        String billNo = deliveryReceiptDO.getBillNo();
//
//        if (deliveryReceiptDO.getSyncNsStatus() == 1) {
//            throw new Exception("发货明细已同步NS系统，请勿重复同步");
//        }
//
//        //查询装箱明细
//        List<BoxupDetailVO> materialsList = boxupMainService.beenPackList(billNo);
//        if (CollectionUtils.isEmpty(materialsList)) {
//            throw new Exception("尚无装箱明细，请先装箱");
//        }
//
//        //过滤已发货
//        List<String> boxupIds = materialsList.stream().map(BoxupDetailVO::getBoxupId).collect(Collectors.toList());
//        BoxupMainVO mainVO = new BoxupMainVO();
//        mainVO.setBoxupIdList(boxupIds);
//        mainVO.setDeliveryStatus(1);
//        List<BoxupMainDO> mainDOS = boxupMainMapper.list(mainVO);
//        List<String> deliveryBoxupIds = mainDOS.stream().map(BoxupMainDO::getBoxupId).distinct().collect(Collectors.toList());
//        List<BoxupDetailVO> deliverySyncList = materialsList.stream().filter(item -> deliveryBoxupIds.contains(item.getBoxupId()))
//                .collect(Collectors.toList());
//        if (CollectionUtils.isEmpty(deliverySyncList)) {
//            throw new Exception("尚无发货明细，请确认发货");
//        }
//
//        List<BoxupDetailVO> syncList = deliverySyncList.stream().filter(m -> m.getSyncNsStatus() == 0).collect(Collectors.toList());
//
//        if (CollectionUtils.isEmpty(syncList)) {
//            throw new Exception("已发货明细已全部同步NS系统，请勿重复同步");
//        }
//
//        //查询创建人
//        Map<String, ProfileDTO> profileDTOMap = new HashMap<>();
//        List<String> userIds = deliverySyncList.stream().map(BoxupDetailVO::getCreateId).collect(Collectors.toList());
//        ActionResult<List<ProfileDTO>> profileResult = authClient.listByIds(userIds.toArray(new String[userIds.size()]));
//        if (ErrorCode.Success.getCode() != profileResult.getCode()) {
//            throw new Exception(profileResult.getMessage());
//        }
//        List<ProfileDTO> profileList = profileResult.getValue();
//        if (CollectionUtils.isEmpty(profileList)) {
//            throw new Exception("创建人及部门编号不能为空");
//        }
//        profileDTOMap = profileList.stream().collect(Collectors.toMap(ProfileDTO::getUserId, Function.identity(), (k1, k2) -> k2));
//
//        //查询销售订单号
//        Map<String, DeliveryNoteDO> deliveryNoteMap = new HashMap<>();
//        List<String> noteNoList = syncList.stream().map(BoxupDetailVO::getDeliveryNoteId).distinct().collect(Collectors.toList());
//        noteNoList = CollectionUtils.isEmpty(noteNoList) ? Lists.newArrayList("-1") : noteNoList;
//        DeliveryNoteVO model = new DeliveryNoteVO();
//        model.setIds(noteNoList);
//        List<DeliveryNoteDO> noteDOList = deliveryNoteMapper.list(model);
//        deliveryNoteMap = noteDOList.stream().collect(Collectors.toMap(DeliveryNoteDO::getId, Function.identity(), (k1, k2) -> k2));
//
//        List<PushDeliveryDetailReq> detailReqList = Lists.newArrayList();
//        PushDeliveryDetailReq detailReq;
//
//        //自定义行号
//        Integer initLineNum = deliverySyncList.size() - syncList.size();
//
//        for (int i = 0; i < syncList.size(); i++) {
//            BoxupDetailVO detailVO = syncList.get(i);
//            detailReq = new PushDeliveryDetailReq();
//            if (deliveryNoteMap.containsKey(detailVO.getDeliveryNoteId())) {//采购订单号
//                detailReq.setPoNum(deliveryNoteMap.get(detailVO.getDeliveryNoteId()).getSaleNo());
//            }
//            detailReq.setShipNum(billNo);//发货单号
//            detailReq.setLineNum(String.valueOf(initLineNum + i + 1));//行号
//            detailReq.setDate(ToolTime.getStringBySlash(detailVO.getCreateTime()));
//            detailReq.setItemCode(detailVO.getMaterialsNo());
//            detailReq.setItemDesp(detailVO.getMaterialsDes());
//            detailReq.setProductModel(detailVO.getMachineModel());
//            detailReq.setUnit(detailVO.getUnit());
//            // TODO: 2021/4/2 获取进出口采购价
//            detailReq.setUnitPrice(detailVO.getPurchaseUnitPrice());//单价--采购价
//            detailReq.setAmount(detailVO.getQty().multiply(detailVO.getPurchaseUnitPrice()));//金额--采购金额
//            detailReq.setSalesPrice(detailVO.getUnitPriceAfterAdjust());//销售单价
//            detailReq.setSalesAmount(detailVO.getTotalPriceAfterAdjust());//销售总额
//            detailReq.setQuantity(detailVO.getQty());
//            detailReq.setCurrency("CNY");
//            if (profileDTOMap.containsKey(detailVO.getCreateId())) {//负责人
//                detailReq.setPrincipal(profileDTOMap.get(detailVO.getCreateId()).getSapCode());
//            }
//            detailReq.setMemo(detailVO.getRemark());
//            detailReqList.add(detailReq);
//        }
//
//        String jsonPayload = JSONArray.toJSON(detailReqList).toString();
//
//        LogHelper.monitor("========同步Ns数据内容============" + jsonPayload + "====================");
//        String result = NsTokenAuth.callWithHttpPost(deliveryUrl, consumerKey, consumerSecret,
//                tokenId, tokenSecret, realm, jsonPayload).getBody();
//        Map map = JSONArray.parseObject(result);
//        if (null != map) {
//            if (null != map.get("success") && (boolean) map.get("success")) {
//                //判断是否全部同步或部分同步
//                if (deliveryReceiptDO.getDeliveryStatus().equals("1")) {//全部
//                    deliveryReceiptDO.setSyncNsStatus(1);
//                } else if (deliveryReceiptDO.getDeliveryStatus().equals("4")) {//部分
//                    deliveryReceiptDO.setSyncNsStatus(2);
//                }
//
//                boolean success = deliveryReceiptMapper.update(deliveryReceiptDO) > 0;
//                if (!success) {
//                    throw new Exception("更新进出口运单发货明细同步NS状态失败");
//                } else {
//                    BoxupDetailDO detailDO;
//                    //更新装箱明细状态
//                    for (BoxupDetailVO boxupDetailVO : syncList) {
//                        detailDO = new BoxupDetailDO();
//                        detailDO.setSyncNsStatus(1);
//                        detailDO.setBoxupId(boxupDetailVO.getBoxupId());
//                        detailDO.setBarcode(boxupDetailVO.getBarcode());
//                        if (boxupDetailMapper.update(detailDO) <= 0) {
//                            throw new Exception("更新装箱明细【" + boxupDetailVO.getBoxupNo() + "--" + boxupDetailVO.getBarcode() + "】同步NS状态失败");
//                        }
//                    }
//                }
//            } else {
//                throw new Exception((String) map.get("message"));
//            }
//        } else {
//            throw new Exception("发货明细同步NS失败");
//        }
//
//        return ErrorCode.Success;
//
//    }

    public PrintInfoVO getPrintBoxupInfo(String billId) throws Exception {
        DeliveryReceiptDO deliveryReceiptDO = deliveryReceiptMapper.item(billId);
        if (deliveryReceiptDO == null) {
            throw new Exception("发货单不存在");
        }

        BoxupMainVO mainVO = new BoxupMainVO();
        mainVO.setDeliveryReceiptId(deliveryReceiptDO.getId());
        mainVO.setDeliveryReceiptNo(deliveryReceiptDO.getBillNo());
        List<BoxupMainDO> mainDOList = boxupMainMapper.list(mainVO);

        if (CollectionUtils.isEmpty(mainDOList)) {
            throw new Exception("装箱清单不存在");
        }

        List<BoxupDetailVO> materialsList = boxupMainService.beenPackList(deliveryReceiptDO.getBillNo());

        PrintInfoVO printInfoVO = new PrintInfoVO();
        printInfoVO.setBillNo(deliveryReceiptDO.getBillNo());

        List<BoxInfoVO> boxInfoVOs = new ArrayList<BoxInfoVO>();

        for (BoxupMainDO mainDO : mainDOList) {
            BoxInfoVO boxInfoVO = new BoxInfoVO();
            boxInfoVO.setBoxupId(mainDO.getBoxupId());
            boxInfoVO.setBoxupNo(mainDO.getBoxupNo());
            String boxupNo = mainDO.getBoxupNo();
            List<BoxupDetailVO> boxupMaterials = new ArrayList<BoxupDetailVO>();
            for (BoxupDetailVO boxupDetailVO : materialsList) {
                if (boxupNo.equals(boxupDetailVO.getBoxupNo())) {
                    boxupMaterials.add(boxupDetailVO);
                }
            }
            boxInfoVO.setMaterials(boxupMaterials);
            boxInfoVOs.add(boxInfoVO);
        }

        printInfoVO.setBoxInfos(boxInfoVOs);
        return printInfoVO;
    }

    public PrintInfoVO getSinglePrintBoxupInfo(String boxupId) throws Exception {
        DeliveryReceiptDO deliveryReceiptDO = deliveryReceiptMapper.getInfoByBoxupId(boxupId);
        if (deliveryReceiptDO == null) {
            throw new Exception("发货单不存在");
        }

        BoxupMainDO mainDO = boxupMainMapper.item(boxupId);

        if (mainDO == null) {
            throw new Exception("装箱清单不存在");
        }

        List<BoxupDetailVO> materialsList = boxupMainService.beenPackList(deliveryReceiptDO.getBillNo());

        PrintInfoVO printInfoVO = new PrintInfoVO();
        printInfoVO.setBillNo(deliveryReceiptDO.getBillNo());

        List<BoxInfoVO> boxInfoVOs = new ArrayList<BoxInfoVO>();

        BoxInfoVO boxInfoVO = new BoxInfoVO();
        boxInfoVO.setBoxupId(mainDO.getBoxupId());
        boxInfoVO.setBoxupNo(mainDO.getBoxupNo());
        String boxupNo = mainDO.getBoxupNo();
        List<BoxupDetailVO> boxupMaterials = new ArrayList<BoxupDetailVO>();
        for (BoxupDetailVO boxupDetailVO : materialsList) {
            if (boxupNo.equals(boxupDetailVO.getBoxupNo())) {
                boxupMaterials.add(boxupDetailVO);
            }
        }
        boxInfoVO.setMaterials(boxupMaterials);
        boxInfoVOs.add(boxInfoVO);

        printInfoVO.setBoxInfos(boxInfoVOs);
        return printInfoVO;
    }

    public Integer countWaitAuditData(String orgId) {
        Integer count = deliveryReceiptMapper.countWaitAuditData(orgId);
        return count == null ? 0 : count;
    }
}
